aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf')
-rw-r--r--src/google/protobuf/SEBS240
-rw-r--r--src/google/protobuf/any.cc100
-rw-r--r--src/google/protobuf/any.h90
-rw-r--r--src/google/protobuf/any.pb.cc482
-rw-r--r--src/google/protobuf/any.pb.h250
-rw-r--r--src/google/protobuf/any.proto104
-rw-r--r--src/google/protobuf/any_test.cc89
-rw-r--r--src/google/protobuf/any_test.proto41
-rw-r--r--src/google/protobuf/api.pb.cc1401
-rw-r--r--src/google/protobuf/api.pb.h703
-rw-r--r--src/google/protobuf/api.proto106
-rwxr-xr-x[-rw-r--r--]src/google/protobuf/arena.cc79
-rw-r--r--src/google/protobuf/arena.h464
-rw-r--r--src/google/protobuf/arena_nc_test.py10
-rw-r--r--src/google/protobuf/arena_test_util.cc49
-rw-r--r--src/google/protobuf/arena_test_util.h60
-rw-r--r--src/google/protobuf/arena_unittest.cc310
-rw-r--r--src/google/protobuf/compiler/code_generator.h31
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc423
-rw-r--r--src/google/protobuf/compiler/command_line_interface.h12
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc109
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.cc32
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.h6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.cc127
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.h9
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.h28
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc553
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.h29
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_generator.cc1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc76
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h28
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.cc147
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.h3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc759
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.h29
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc303
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.h17
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_options.h5
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.cc66
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.h9
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_service.cc2
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc169
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.h9
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto18
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto43
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc52
-rw-r--r--src/google/protobuf/compiler/cpp/test_large_enum_value.proto43
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_enum.cc78
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_enum.h63
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_enum_field.cc119
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_enum_field.h77
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_field_base.cc425
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_field_base.h103
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_generator.cc100
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_generator.h58
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc54
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_helpers.cc393
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_helpers.h132
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_map_field.cc137
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_map_field.h71
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message.cc482
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message.h89
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message_field.cc193
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message_field.h86
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_names.h82
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_primitive_field.cc214
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_primitive_field.h88
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc125
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h73
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc140
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h71
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc123
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h71
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc66
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_source_generator_base.h64
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc295
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_umbrella_class.h70
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc207
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_wrapper_field.h85
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.cc16
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field_lite.cc967
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field_lite.h159
-rw-r--r--src/google/protobuf/compiler/java/java_extension.cc8
-rw-r--r--src/google/protobuf/compiler/java/java_extension.h12
-rw-r--r--src/google/protobuf/compiler/java/java_field.cc108
-rw-r--r--src/google/protobuf/compiler/java/java_field.h31
-rw-r--r--src/google/protobuf/compiler/java/java_file.cc98
-rw-r--r--src/google/protobuf/compiler/java/java_generator_factory.cc8
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.cc4
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.h20
-rw-r--r--src/google/protobuf/compiler/java/java_lazy_message_field.cc236
-rw-r--r--src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc708
-rw-r--r--src/google/protobuf/compiler/java/java_lazy_message_field_lite.h118
-rw-r--r--src/google/protobuf/compiler/java/java_map_field.cc120
-rw-r--r--src/google/protobuf/compiler/java/java_map_field.h3
-rw-r--r--src/google/protobuf/compiler/java/java_map_field_lite.cc459
-rw-r--r--src/google/protobuf/compiler/java/java_map_field_lite.h78
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc1102
-rw-r--r--src/google/protobuf/compiler/java/java_message.h21
-rw-r--r--src/google/protobuf/compiler/java/java_message_builder.cc661
-rw-r--r--src/google/protobuf/compiler/java/java_message_builder.h86
-rw-r--r--src/google/protobuf/compiler/java/java_message_builder_lite.cc192
-rw-r--r--src/google/protobuf/compiler/java/java_message_builder_lite.h83
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.cc410
-rw-r--r--src/google/protobuf/compiler/java/java_message_field_lite.cc944
-rw-r--r--src/google/protobuf/compiler/java/java_message_field_lite.h157
-rw-r--r--src/google/protobuf/compiler/java/java_message_lite.cc1174
-rw-r--r--src/google/protobuf/compiler/java/java_message_lite.h91
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.cc18
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field_lite.cc892
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field_lite.h163
-rw-r--r--src/google/protobuf/compiler/java/java_shared_code_generator.cc2
-rw-r--r--src/google/protobuf/compiler/java/java_string_field.cc4
-rw-r--r--src/google/protobuf/compiler/java/java_string_field_lite.cc1013
-rw-r--r--src/google/protobuf/compiler/java/java_string_field_lite.h158
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum.cc40
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum_field.cc32
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum_field.h1
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_extension.cc2
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_field.cc68
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_field.h11
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_generator.cc15
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_helpers.cc27
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_helpers.h10
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_map_field.cc186
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_map_field.h70
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message.cc151
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message.h2
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message_field.cc110
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message_field.h25
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_params.h20
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_primitive_field.cc106
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_primitive_field.h28
-rw-r--r--src/google/protobuf/compiler/main.cc12
-rw-r--r--src/google/protobuf/compiler/mock_code_generator.cc8
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_enum.cc198
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_enum.h73
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc144
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_enum_field.h78
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_extension.cc136
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_extension.h69
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_field.cc434
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_field.h168
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_file.cc371
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_file.h97
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_generator.cc86
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_generator.h60
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers.cc1045
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers.h173
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc257
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_map_field.cc163
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_map_field.h64
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_message.cc647
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_message.h94
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_message_field.cc96
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_message_field.h74
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_oneof.cc138
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_oneof.h77
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc171
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h82
-rw-r--r--src/google/protobuf/compiler/parser.cc174
-rw-r--r--src/google/protobuf/compiler/parser.h45
-rw-r--r--src/google/protobuf/compiler/parser_unittest.cc335
-rw-r--r--src/google/protobuf/compiler/plugin.cc41
-rw-r--r--src/google/protobuf/compiler/plugin.pb.cc437
-rw-r--r--src/google/protobuf/compiler/plugin.pb.h159
-rw-r--r--src/google/protobuf/compiler/plugin.proto2
-rw-r--r--src/google/protobuf/compiler/python/python_generator.cc30
-rw-r--r--src/google/protobuf/compiler/python/python_generator.h3
-rw-r--r--src/google/protobuf/compiler/ruby/ruby_generated_code.proto67
-rw-r--r--src/google/protobuf/compiler/ruby/ruby_generated_code.rb74
-rw-r--r--src/google/protobuf/compiler/ruby/ruby_generator.cc124
-rw-r--r--src/google/protobuf/compiler/ruby/ruby_generator.h3
-rw-r--r--src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc123
-rw-r--r--src/google/protobuf/compiler/subprocess.cc2
-rw-r--r--src/google/protobuf/descriptor.cc271
-rw-r--r--src/google/protobuf/descriptor.h95
-rw-r--r--src/google/protobuf/descriptor.pb.cc5140
-rw-r--r--src/google/protobuf/descriptor.pb.h1865
-rw-r--r--src/google/protobuf/descriptor.proto81
-rw-r--r--src/google/protobuf/descriptor_database.cc28
-rw-r--r--src/google/protobuf/descriptor_database.h4
-rw-r--r--src/google/protobuf/descriptor_database_unittest.cc6
-rw-r--r--src/google/protobuf/descriptor_pb2_test.py54
-rw-r--r--src/google/protobuf/descriptor_unittest.cc250
-rw-r--r--src/google/protobuf/duration.pb.cc407
-rw-r--r--src/google/protobuf/duration.pb.h172
-rw-r--r--src/google/protobuf/duration.proto94
-rw-r--r--src/google/protobuf/empty.pb.cc283
-rw-r--r--src/google/protobuf/empty.pb.h130
-rw-r--r--src/google/protobuf/empty.proto51
-rw-r--r--src/google/protobuf/extension_set.cc77
-rw-r--r--src/google/protobuf/extension_set.h6
-rw-r--r--src/google/protobuf/extension_set_heavy.cc9
-rw-r--r--src/google/protobuf/field_mask.pb.cc395
-rw-r--r--src/google/protobuf/field_mask.pb.h201
-rw-r--r--src/google/protobuf/field_mask.proto163
-rw-r--r--src/google/protobuf/generated_enum_reflection.h5
-rw-r--r--src/google/protobuf/generated_enum_util.h46
-rw-r--r--src/google/protobuf/generated_message_reflection.cc47
-rw-r--r--src/google/protobuf/generated_message_reflection.h37
-rw-r--r--src/google/protobuf/generated_message_util.h13
-rw-r--r--src/google/protobuf/io/coded_stream.cc181
-rw-r--r--src/google/protobuf/io/coded_stream.h144
-rw-r--r--src/google/protobuf/io/coded_stream_inl.h17
-rw-r--r--src/google/protobuf/io/coded_stream_unittest.cc4
-rw-r--r--src/google/protobuf/io/gzip_stream.cc3
-rw-r--r--src/google/protobuf/io/printer.cc72
-rw-r--r--src/google/protobuf/io/printer.h32
-rw-r--r--src/google/protobuf/io/tokenizer.cc9
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl_lite.h2
-rw-r--r--src/google/protobuf/io/zero_copy_stream_unittest.cc2
-rw-r--r--src/google/protobuf/lite_unittest.cc380
-rw-r--r--src/google/protobuf/map.h195
-rw-r--r--src/google/protobuf/map_entry.h329
-rw-r--r--src/google/protobuf/map_entry_lite.h411
-rw-r--r--src/google/protobuf/map_field.cc24
-rw-r--r--src/google/protobuf/map_field.h93
-rw-r--r--src/google/protobuf/map_field_inl.h299
-rw-r--r--src/google/protobuf/map_field_lite.h278
-rw-r--r--src/google/protobuf/map_field_test.cc72
-rw-r--r--src/google/protobuf/map_lite_test_util.cc93
-rw-r--r--src/google/protobuf/map_lite_test_util.h80
-rw-r--r--src/google/protobuf/map_lite_unittest.proto98
-rw-r--r--src/google/protobuf/map_test.cc105
-rw-r--r--src/google/protobuf/map_test_util.cc272
-rw-r--r--src/google/protobuf/map_test_util.h9
-rw-r--r--src/google/protobuf/map_test_util_impl.h474
-rw-r--r--src/google/protobuf/map_type_handler.h204
-rw-r--r--src/google/protobuf/map_unittest.proto37
-rw-r--r--src/google/protobuf/map_unittest_proto3.proto120
-rw-r--r--src/google/protobuf/message.cc43
-rw-r--r--src/google/protobuf/message.h41
-rw-r--r--src/google/protobuf/message_lite.cc2
-rw-r--r--src/google/protobuf/message_lite.h17
-rw-r--r--src/google/protobuf/message_unittest.cc31
-rw-r--r--src/google/protobuf/new_delete_capture.cc121
-rw-r--r--src/google/protobuf/new_delete_capture.h175
-rw-r--r--src/google/protobuf/preserve_unknown_enum_test.cc111
-rw-r--r--src/google/protobuf/proto3_arena_unittest.cc10
-rwxr-xr-x[-rw-r--r--]src/google/protobuf/reflection.h302
-rw-r--r--src/google/protobuf/repeated_field.h68
-rw-r--r--src/google/protobuf/repeated_field_reflection_unittest.cc2
-rw-r--r--src/google/protobuf/repeated_field_unittest.cc51
-rw-r--r--src/google/protobuf/source_context.pb.cc387
-rw-r--r--src/google/protobuf/source_context.pb.h185
-rw-r--r--src/google/protobuf/source_context.proto47
-rw-r--r--src/google/protobuf/struct.pb.cc1455
-rw-r--r--src/google/protobuf/struct.pb.h764
-rw-r--r--src/google/protobuf/struct.proto90
-rw-r--r--src/google/protobuf/stubs/atomicops.h1
-rw-r--r--src/google/protobuf/stubs/atomicops_internals_generic_gcc.h4
-rw-r--r--src/google/protobuf/stubs/atomicops_internals_mips_gcc.h4
-rw-r--r--src/google/protobuf/stubs/atomicops_internals_pnacl.h176
-rw-r--r--src/google/protobuf/stubs/bytestream.cc196
-rw-r--r--src/google/protobuf/stubs/bytestream.h348
-rw-r--r--src/google/protobuf/stubs/bytestream_unittest.cc146
-rw-r--r--src/google/protobuf/stubs/callback.h463
-rw-r--r--src/google/protobuf/stubs/casts.h10
-rw-r--r--src/google/protobuf/stubs/common.cc28
-rw-r--r--src/google/protobuf/stubs/common.h1071
-rw-r--r--src/google/protobuf/stubs/common_unittest.cc2
-rwxr-xr-x[-rw-r--r--]src/google/protobuf/stubs/hash.h200
-rw-r--r--src/google/protobuf/stubs/logging.h235
-rw-r--r--src/google/protobuf/stubs/macros.h168
-rw-r--r--src/google/protobuf/stubs/mathlimits.cc144
-rw-r--r--src/google/protobuf/stubs/mathlimits.h279
-rw-r--r--src/google/protobuf/stubs/mathutil.h150
-rw-r--r--src/google/protobuf/stubs/mutex.h148
-rw-r--r--src/google/protobuf/stubs/once.h1
-rw-r--r--src/google/protobuf/stubs/platform_macros.h16
-rw-r--r--src/google/protobuf/stubs/port.h382
-rw-r--r--src/google/protobuf/stubs/scoped_ptr.h236
-rw-r--r--src/google/protobuf/stubs/singleton.h6
-rw-r--r--src/google/protobuf/stubs/status.cc135
-rw-r--r--src/google/protobuf/stubs/status.h116
-rw-r--r--src/google/protobuf/stubs/status_macros.h89
-rw-r--r--src/google/protobuf/stubs/status_test.cc131
-rw-r--r--src/google/protobuf/stubs/statusor.cc46
-rw-r--r--src/google/protobuf/stubs/statusor.h259
-rw-r--r--src/google/protobuf/stubs/statusor_test.cc274
-rw-r--r--src/google/protobuf/stubs/stringpiece.cc268
-rw-r--r--src/google/protobuf/stubs/stringpiece.h440
-rw-r--r--src/google/protobuf/stubs/stringpiece_unittest.cc793
-rw-r--r--src/google/protobuf/stubs/strutil.cc1000
-rw-r--r--src/google/protobuf/stubs/strutil.h380
-rw-r--r--src/google/protobuf/stubs/strutil_unittest.cc739
-rw-r--r--src/google/protobuf/stubs/time.cc366
-rw-r--r--src/google/protobuf/stubs/time.h75
-rw-r--r--src/google/protobuf/stubs/time_test.cc208
-rw-r--r--src/google/protobuf/stubs/type_traits.h6
-rw-r--r--src/google/protobuf/testdata/golden_message_proto3bin0 -> 248 bytes
-rw-r--r--src/google/protobuf/testdata/map_test_data.txt140
-rw-r--r--src/google/protobuf/testing/file.cc4
-rw-r--r--src/google/protobuf/testing/file.h3
-rw-r--r--src/google/protobuf/testing/googletest.cc25
-rw-r--r--src/google/protobuf/testing/zcgunzip.cc11
-rw-r--r--src/google/protobuf/testing/zcgzip.cc11
-rw-r--r--src/google/protobuf/text_format.cc274
-rw-r--r--src/google/protobuf/text_format.h31
-rw-r--r--src/google/protobuf/text_format_unittest.cc31
-rw-r--r--src/google/protobuf/timestamp.pb.cc407
-rw-r--r--src/google/protobuf/timestamp.pb.h172
-rw-r--r--src/google/protobuf/timestamp.proto106
-rw-r--r--src/google/protobuf/type.pb.cc2899
-rw-r--r--src/google/protobuf/type.pb.h1516
-rw-r--r--src/google/protobuf/type.proto198
-rw-r--r--src/google/protobuf/unittest.proto6
-rw-r--r--src/google/protobuf/unittest_drop_unknown_fields.proto13
-rw-r--r--src/google/protobuf/unittest_enormous_descriptor.proto3
-rw-r--r--src/google/protobuf/unittest_import_proto3.proto68
-rw-r--r--src/google/protobuf/unittest_import_public_proto3.proto42
-rw-r--r--src/google/protobuf/unittest_no_arena.proto3
-rw-r--r--src/google/protobuf/unittest_no_field_presence.proto56
-rw-r--r--src/google/protobuf/unittest_preserve_unknown_enum.proto19
-rw-r--r--src/google/protobuf/unittest_preserve_unknown_enum2.proto50
-rw-r--r--src/google/protobuf/unittest_proto3.proto388
-rw-r--r--src/google/protobuf/unittest_proto3_arena.proto146
-rw-r--r--src/google/protobuf/unittest_well_known_types.proto112
-rw-r--r--src/google/protobuf/unknown_enum_impl.h23
-rw-r--r--src/google/protobuf/unknown_enum_test.proto1
-rw-r--r--src/google/protobuf/unknown_field_set.cc13
-rw-r--r--src/google/protobuf/unknown_field_set.h7
-rw-r--r--src/google/protobuf/util/field_comparator.cc188
-rw-r--r--src/google/protobuf/util/field_comparator.h259
-rw-r--r--src/google/protobuf/util/field_comparator_test.cc483
-rw-r--r--src/google/protobuf/util/internal/constants.h93
-rw-r--r--src/google/protobuf/util/internal/datapiece.cc286
-rw-r--r--src/google/protobuf/util/internal/datapiece.h212
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter.cc515
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter.h238
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter_test.cc139
-rw-r--r--src/google/protobuf/util/internal/error_listener.cc42
-rw-r--r--src/google/protobuf/util/internal/error_listener.h99
-rw-r--r--src/google/protobuf/util/internal/expecting_objectwriter.h238
-rw-r--r--src/google/protobuf/util/internal/field_mask_utility.cc228
-rw-r--r--src/google/protobuf/util/internal/field_mask_utility.h72
-rw-r--r--src/google/protobuf/util/internal/json_escaping.cc403
-rw-r--r--src/google/protobuf/util/internal/json_escaping.h91
-rw-r--r--src/google/protobuf/util/internal/json_objectwriter.cc175
-rw-r--r--src/google/protobuf/util/internal/json_objectwriter.h206
-rw-r--r--src/google/protobuf/util/internal/json_objectwriter_test.cc285
-rw-r--r--src/google/protobuf/util/internal/json_stream_parser.cc740
-rw-r--r--src/google/protobuf/util/internal/json_stream_parser.h256
-rw-r--r--src/google/protobuf/util/internal/json_stream_parser_test.cc702
-rw-r--r--src/google/protobuf/util/internal/location_tracker.h65
-rw-r--r--src/google/protobuf/util/internal/mock_error_listener.h63
-rw-r--r--src/google/protobuf/util/internal/object_location_tracker.h64
-rw-r--r--src/google/protobuf/util/internal/object_source.h79
-rw-r--r--src/google/protobuf/util/internal/object_writer.cc92
-rw-r--r--src/google/protobuf/util/internal/object_writer.h126
-rw-r--r--src/google/protobuf/util/internal/protostream_objectsource.cc1051
-rw-r--r--src/google/protobuf/util/internal/protostream_objectsource.h245
-rw-r--r--src/google/protobuf/util/internal/protostream_objectsource_test.cc824
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter.cc1557
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter.h455
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter_test.cc1513
-rw-r--r--src/google/protobuf/util/internal/snake2camel_objectwriter.h187
-rw-r--r--src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc311
-rw-r--r--src/google/protobuf/util/internal/structured_objectwriter.h118
-rw-r--r--src/google/protobuf/util/internal/testdata/anys.proto53
-rw-r--r--src/google/protobuf/util/internal/testdata/books.proto171
-rw-r--r--src/google/protobuf/util/internal/testdata/default_value.proto162
-rw-r--r--src/google/protobuf/util/internal/testdata/default_value_test.proto46
-rw-r--r--src/google/protobuf/util/internal/testdata/field_mask.proto71
-rw-r--r--src/google/protobuf/util/internal/testdata/maps.proto57
-rw-r--r--src/google/protobuf/util/internal/testdata/struct.proto45
-rw-r--r--src/google/protobuf/util/internal/testdata/timestamp_duration.proto47
-rw-r--r--src/google/protobuf/util/internal/testdata/wrappers.proto100
-rw-r--r--src/google/protobuf/util/internal/type_info.cc171
-rw-r--r--src/google/protobuf/util/internal/type_info.h87
-rw-r--r--src/google/protobuf/util/internal/type_info_test_helper.cc133
-rw-r--r--src/google/protobuf/util/internal/type_info_test_helper.h98
-rw-r--r--src/google/protobuf/util/internal/utility.cc333
-rw-r--r--src/google/protobuf/util/internal/utility.h187
-rw-r--r--src/google/protobuf/util/json_format_proto3.proto157
-rw-r--r--src/google/protobuf/util/json_util.cc142
-rw-r--r--src/google/protobuf/util/json_util.h136
-rw-r--r--src/google/protobuf/util/json_util_test.cc277
-rw-r--r--src/google/protobuf/util/message_differencer.cc1629
-rw-r--r--src/google/protobuf/util/message_differencer.h808
-rwxr-xr-xsrc/google/protobuf/util/message_differencer_unittest.cc3132
-rw-r--r--src/google/protobuf/util/message_differencer_unittest.proto74
-rw-r--r--src/google/protobuf/util/type_resolver.h75
-rw-r--r--src/google/protobuf/util/type_resolver_util.cc212
-rw-r--r--src/google/protobuf/util/type_resolver_util.h52
-rw-r--r--src/google/protobuf/util/type_resolver_util_test.cc338
-rw-r--r--src/google/protobuf/well_known_types_unittest.cc60
-rw-r--r--src/google/protobuf/wire_format.cc48
-rw-r--r--src/google/protobuf/wire_format.h10
-rw-r--r--src/google/protobuf/wire_format_lite.cc28
-rw-r--r--src/google/protobuf/wire_format_lite.h30
-rw-r--r--src/google/protobuf/wire_format_lite_inl.h21
-rw-r--r--src/google/protobuf/wire_format_unittest.cc166
-rw-r--r--src/google/protobuf/wrappers.pb.cc2419
-rw-r--r--src/google/protobuf/wrappers.pb.h1011
-rw-r--r--src/google/protobuf/wrappers.proto99
398 files changed, 83142 insertions, 6646 deletions
diff --git a/src/google/protobuf/SEBS b/src/google/protobuf/SEBS
deleted file mode 100644
index ba33c732..00000000
--- a/src/google/protobuf/SEBS
+++ /dev/null
@@ -1,240 +0,0 @@
-# **EXPERIMENTAL**
-#
-# See http://sebs.googlecode.com
-#
-# This is an experimental build definition file using the SEBS build system.
-# I (Kenton Varda, maintainer of Protocol Buffers) happen to be the author of
-# SEBS, though SEBS is not a Google project. I'm sticking this file in
-# protobuf's SVN because that's the easiest place for me to put it, and it
-# shouldn't harm anyone. This file is not included in the distribution.
-#
-# Currently, to use this file, you must generate config.h and put it at the
-# top level of the source tree.
-
-_cpp = sebs.import_("//sebs/cpp.sebs")
-
-# ====================================================================
-# Public targets
-
-protobuf_lite = _cpp.Library(
- name = "protobuf-lite",
- srcs = [ "stubs/common.cc",
- "stubs/once.cc",
- "stubs/hash.cc",
- "stubs/hash.h",
- "stubs/map-util.h",
- "stubs/stl_util-inl.h",
- "extension_set.cc",
- "generated_message_util.cc",
- "message_lite.cc",
- "repeated_field.cc",
- "wire_format_lite.cc",
- "io/coded_stream.cc",
- "io/zero_copy_stream.cc",
- "io/zero_copy_stream_impl_lite.cc" ],
- deps = [ _cpp.SystemLibrary(name = "pthread") ])
-
-protobuf = _cpp.Library(
- name = "protobuf",
- srcs = [ "stubs/strutil.cc",
- "stubs/strutil.h",
- "stubs/substitute.cc",
- "stubs/substitute.h",
- "stubs/structurally_valid.cc",
- "descriptor.cc",
- "descriptor.pb.cc",
- "descriptor_database.cc",
- "dynamic_message.cc",
- "extension_set_heavy.cc",
- "generated_message_reflection.cc",
- "message.cc",
- "reflection_ops.cc",
- "service.cc",
- "text_format.cc",
- "unknown_field_set.cc",
- "wire_format.cc",
- "io/gzip_stream.cc",
- "io/printer.cc",
- "io/tokenizer.cc",
- "io/zero_copy_stream_impl.cc",
- "compiler/importer.cc",
- "compiler/parser.cc" ],
- deps = [ protobuf_lite,
- _cpp.SystemLibrary(name = "z") ])
-
-libprotoc = _cpp.Library(
- name = "protoc",
- srcs = [ "compiler/code_generator.cc",
- "compiler/command_line_interface.cc",
- "compiler/cpp/cpp_enum.cc",
- "compiler/cpp/cpp_enum.h",
- "compiler/cpp/cpp_enum_field.cc",
- "compiler/cpp/cpp_enum_field.h",
- "compiler/cpp/cpp_extension.cc",
- "compiler/cpp/cpp_extension.h",
- "compiler/cpp/cpp_field.cc",
- "compiler/cpp/cpp_field.h",
- "compiler/cpp/cpp_file.cc",
- "compiler/cpp/cpp_file.h",
- "compiler/cpp/cpp_generator.cc",
- "compiler/cpp/cpp_helpers.cc",
- "compiler/cpp/cpp_helpers.h",
- "compiler/cpp/cpp_message.cc",
- "compiler/cpp/cpp_message.h",
- "compiler/cpp/cpp_message_field.cc",
- "compiler/cpp/cpp_message_field.h",
- "compiler/cpp/cpp_primitive_field.cc",
- "compiler/cpp/cpp_primitive_field.h",
- "compiler/cpp/cpp_service.cc",
- "compiler/cpp/cpp_service.h",
- "compiler/cpp/cpp_string_field.cc",
- "compiler/cpp/cpp_string_field.h",
- "compiler/java/java_enum.cc",
- "compiler/java/java_enum.h",
- "compiler/java/java_enum_field.cc",
- "compiler/java/java_enum_field.h",
- "compiler/java/java_extension.cc",
- "compiler/java/java_extension.h",
- "compiler/java/java_field.cc",
- "compiler/java/java_field.h",
- "compiler/java/java_file.cc",
- "compiler/java/java_file.h",
- "compiler/java/java_generator.cc",
- "compiler/java/java_helpers.cc",
- "compiler/java/java_helpers.h",
- "compiler/java/java_message.cc",
- "compiler/java/java_message.h",
- "compiler/java/java_message_field.cc",
- "compiler/java/java_message_field.h",
- "compiler/java/java_primitive_field.cc",
- "compiler/java/java_primitive_field.h",
- "compiler/java/java_service.cc",
- "compiler/java/java_service.h",
- "compiler/python/python_generator.cc" ],
- deps = [ protobuf ])
-
-protoc = _cpp.Binary(
- name = "protoc",
- srcs = [ "compiler/main.cc" ],
- deps = [ libprotoc ])
-
-# ====================================================================
-# ProtobufLibrary rule class
-
-class ProtobufLibrary(sebs.Rule):
- argument_spec = sebs.ArgumentSpec(srcs = [sebs.Artifact],
- deps = ([sebs.Rule], []),
- lite = (bool, False))
-
- def _expand(self, args):
- for dep in args.deps:
- if not isinstance(dep, ProtobufLibrary):
- raise sebs.DefinitionError(
- "Dependency of ProtobufLibrary is not a ProtobufLibrary: %s" % dep)
-
- protoc.expand_once()
-
- # We must build protoc for the host configuration to allow cross-compiling.
- host_protoc = self.context.configured_artifact(protoc.binary, "host")
-
- protoc_action = self.context.action(self, "protobuf")
- protoc_args = [host_protoc, "-Isrc", "-Itmp", "-Iinclude","--cpp_out=tmp"]
-
- cpp_srcs = []
- for src in args.srcs:
- protoc_args.append(src)
-
- # We cannot build .proto files from other packages because the .pb.cc
- # and .pb.h files would be written to that package, and we aren't allowed
- # to write to other packages.
- if self.context.local_filename(src) is None:
- raise sebs.DefinitionError(
- "Source file is not in this package: %s" % src)
-
- cc_artifact = self.context.derived_artifact(src, ".pb.cc", protoc_action)
- header_artifact = self.context.derived_artifact(
- src, ".pb.h", protoc_action)
-
- cpp_srcs.append(cc_artifact)
- cpp_srcs.append(header_artifact)
-
- protoc_action.set_command(
- sebs.SubprocessCommand(protoc_action, protoc_args, implicit = cpp_srcs))
-
- deps = list(args.deps)
- if args.lite:
- deps.append(protobuf_lite)
- else:
- deps.append(protobuf)
-
- self.__cpp_library = _cpp.Library(srcs = cpp_srcs, deps = deps,
- context = self.context)
- self.__cpp_library.label = self.label
- self.outputs = []
-
- def as_cpp_library(self):
- self.expand_once()
- return self.__cpp_library
-
-# ====================================================================
-# Tests
-
-_lite_test_protos = ProtobufLibrary(
- srcs = [ "unittest_lite.proto",
- "unittest_import_lite.proto" ],
- lite = True)
-_test_protos = ProtobufLibrary(
- srcs = [ "unittest.proto",
- "unittest_empty.proto",
- "unittest_import.proto",
- "unittest_mset.proto",
- "unittest_optimize_for.proto",
- "unittest_embed_optimize_for.proto",
- "unittest_custom_options.proto",
- "unittest_lite_imports_nonlite.proto",
- "compiler/cpp/cpp_test_bad_identifiers.proto" ],
- deps = [ _lite_test_protos ])
-
-_test_util = _cpp.Library(
- name = "test_util",
- srcs = [ "test_util.cc",
- "test_util.h",
- "testing/googletest.cc",
- "testing/googletest.h",
- "testing/file.cc",
- "testing/file.h" ],
- deps = [ protobuf, _test_protos, _cpp.SystemLibrary(name = "gtest")] )
-
-protobuf_lite_test = _cpp.Test(
- srcs = [ "lite_unittest.cc",
- "test_util_lite.cc",
- "test_util_lite.h" ],
- deps = [ _lite_test_protos ])
-
-protobuf_test = _cpp.Test(
- srcs = [ "stubs/common_unittest.cc",
- "stubs/once_unittest.cc",
- "stubs/strutil_unittest.cc",
- "stubs/structurally_valid_unittest.cc",
- "descriptor_database_unittest.cc",
- "descriptor_unittest.cc",
- "dynamic_message_unittest.cc",
- "extension_set_unittest.cc",
- "generated_message_reflection_unittest.cc",
- "message_unittest.cc",
- "reflection_ops_unittest.cc",
- "repeated_field_unittest.cc",
- "text_format_unittest.cc",
- "unknown_field_set_unittest.cc",
- "wire_format_unittest.cc",
- "io/coded_stream_unittest.cc",
- "io/printer_unittest.cc",
- "io/tokenizer_unittest.cc",
- "io/zero_copy_stream_unittest.cc",
- "compiler/command_line_interface_unittest.cc",
- "compiler/importer_unittest.cc",
- "compiler/parser_unittest.cc",
- "compiler/cpp/cpp_bootstrap_unittest.cc",
- "compiler/cpp/cpp_unittest.cc" ],
- deps = [ protobuf, libprotoc, _test_util,
- _cpp.SystemLibrary(name = "gtest_main") ])
diff --git a/src/google/protobuf/any.cc b/src/google/protobuf/any.cc
new file mode 100644
index 00000000..c66fdfad
--- /dev/null
+++ b/src/google/protobuf/any.cc
@@ -0,0 +1,100 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/any.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+namespace {
+string GetTypeUrl(const Descriptor* message) {
+ return string(kTypeGoogleApisComPrefix) + message->full_name();
+}
+
+} // namespace
+
+const char kAnyFullTypeName[] = "google.protobuf.Any";
+const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/";
+
+AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value)
+ : type_url_(type_url), value_(value) {
+}
+
+void AnyMetadata::PackFrom(const Message& message) {
+ type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(),
+ GetTypeUrl(message.GetDescriptor()));
+ message.SerializeToString(value_->MutableNoArena(
+ &::google::protobuf::internal::GetEmptyStringAlreadyInited()));
+}
+
+bool AnyMetadata::UnpackTo(Message* message) const {
+ if (!InternalIs(message->GetDescriptor())) {
+ return false;
+ }
+ return message->ParseFromString(
+ value_->GetNoArena(&::google::protobuf::internal::GetEmptyString()));
+}
+
+bool AnyMetadata::InternalIs(const Descriptor* descriptor) const {
+ return type_url_->GetNoArena(
+ &::google::protobuf::internal::GetEmptyString()) ==
+ GetTypeUrl(descriptor);
+}
+
+bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) {
+ const int prefix_len = strlen(kTypeGoogleApisComPrefix);
+ if (strncmp(type_url.c_str(), kTypeGoogleApisComPrefix, prefix_len) == 0) {
+ full_type_name->assign(type_url.data() + prefix_len,
+ type_url.size() - prefix_len);
+ return true;
+ }
+ return true;
+}
+
+
+bool GetAnyFieldDescriptors(const Message& message,
+ const FieldDescriptor** type_url_field,
+ const FieldDescriptor** value_field) {
+ const Descriptor* descriptor = message.GetDescriptor();
+ if (descriptor->full_name() != kAnyFullTypeName) {
+ return false;
+ }
+ *type_url_field = descriptor->FindFieldByNumber(1);
+ *value_field = descriptor->FindFieldByNumber(2);
+ return (*type_url_field != NULL &&
+ (*type_url_field)->type() == FieldDescriptor::TYPE_STRING &&
+ *value_field != NULL &&
+ (*value_field)->type() == FieldDescriptor::TYPE_BYTES);
+}
+
+} // namespace internal
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/any.h b/src/google/protobuf/any.h
new file mode 100644
index 00000000..f681eceb
--- /dev/null
+++ b/src/google/protobuf/any.h
@@ -0,0 +1,90 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_ANY_H__
+#define GOOGLE_PROTOBUF_ANY_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/message.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Helper class used to implement google::protobuf::Any.
+class LIBPROTOBUF_EXPORT AnyMetadata {
+ typedef ArenaStringPtr UrlType;
+ typedef ArenaStringPtr ValueType;
+ public:
+ // AnyMetadata does not take ownership of "type_url" and "value".
+ AnyMetadata(UrlType* type_url, ValueType* value);
+
+ void PackFrom(const Message& message);
+
+ bool UnpackTo(Message* message) const;
+
+ template<typename T>
+ bool Is() const {
+ return InternalIs(T::default_instance().GetDescriptor());
+ }
+
+ private:
+ bool InternalIs(const Descriptor* message) const;
+
+ UrlType* type_url_;
+ ValueType* value_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata);
+};
+
+extern const char kAnyFullTypeName[]; // "google.protobuf.Any".
+extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/".
+
+// Get the proto type name from Any::type_url value. For example, passing
+// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in
+// *full_type_name. Returns false if type_url does not start with
+// "type.googleapis.com".
+bool ParseAnyTypeUrl(const string& type_url, string* full_type_name);
+
+// See if message is of type google.protobuf.Any, if so, return the descriptors
+// for "type_url" and "value" fields.
+bool GetAnyFieldDescriptors(const Message& message,
+ const FieldDescriptor** type_url_field,
+ const FieldDescriptor** value_field);
+
+} // namespace internal
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_ANY_H__
diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc
new file mode 100644
index 00000000..c2e58131
--- /dev/null
+++ b/src/google/protobuf/any.pb.cc
@@ -0,0 +1,482 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/any.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "google/protobuf/any.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* Any_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ Any_reflection_ = NULL;
+
+} // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
+ const ::google::protobuf::FileDescriptor* file =
+ ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+ "google/protobuf/any.proto");
+ GOOGLE_CHECK(file != NULL);
+ Any_descriptor_ = file->message_type(0);
+ static const int Any_offsets_[2] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, type_url_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, value_),
+ };
+ Any_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ Any_descriptor_,
+ Any::default_instance_,
+ Any_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(Any),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+ ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+ &protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ Any_descriptor_, &Any::default_instance());
+}
+
+} // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fany_2eproto() {
+ delete Any::default_instance_;
+ delete Any_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fany_2eproto() {
+ static bool already_here = false;
+ if (already_here) return;
+ already_here = true;
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ ::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);
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+ "google/protobuf/any.proto", &protobuf_RegisterTypes);
+ Any::default_instance_ = new Any();
+ Any::default_instance_->InitAsDefaultInstance();
+ ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fany_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fany_2eproto {
+ StaticDescriptorInitializer_google_2fprotobuf_2fany_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
+ }
+} static_descriptor_initializer_google_2fprotobuf_2fany_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+ GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+} // namespace
+
+
+// ===================================================================
+
+void Any::PackFrom(const ::google::protobuf::Message& message) {
+ _any_metadata_.PackFrom(message);
+}
+
+bool Any::UnpackTo(::google::protobuf::Message* message) const {
+ return _any_metadata_.UnpackTo(message);
+}
+
+#ifndef _MSC_VER
+const int Any::kTypeUrlFieldNumber;
+const int Any::kValueFieldNumber;
+#endif // !_MSC_VER
+
+Any::Any()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL), _any_metadata_(&type_url_, &value_) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.Any)
+}
+
+void Any::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+Any::Any(const Any& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL),
+ _any_metadata_(&type_url_, &value_) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.Any)
+}
+
+void Any::SharedCtor() {
+ _is_default_instance_ = false;
+ ::google::protobuf::internal::GetEmptyString();
+ _cached_size_ = 0;
+ type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+Any::~Any() {
+ // @@protoc_insertion_point(destructor:google.protobuf.Any)
+ SharedDtor();
+}
+
+void Any::SharedDtor() {
+ type_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (this != default_instance_) {
+ }
+}
+
+void Any::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Any::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Any_descriptor_;
+}
+
+const Any& Any::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
+ return *default_instance_;
+}
+
+Any* Any::default_instance_ = NULL;
+
+Any* Any::New(::google::protobuf::Arena* arena) const {
+ Any* n = new Any;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void Any::Clear() {
+ 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
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.Any)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional string type_url = 1;
+ case 1: {
+ if (tag == 10) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_type_url()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->type_url().data(), this->type_url().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.Any.type_url");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(18)) goto parse_value;
+ break;
+ }
+
+ // optional bytes value = 2;
+ case 2: {
+ if (tag == 18) {
+ parse_value:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+ input, this->mutable_value()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.Any)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.Any)
+ return false;
+#undef DO_
+}
+
+void Any::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.Any)
+ // optional string type_url = 1;
+ if (this->type_url().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->type_url().data(), this->type_url().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Any.type_url");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 1, this->type_url(), output);
+ }
+
+ // optional bytes value = 2;
+ if (this->value().size() > 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
+ 2, this->value(), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.Any)
+}
+
+::google::protobuf::uint8* Any::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any)
+ // optional string type_url = 1;
+ if (this->type_url().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->type_url().data(), this->type_url().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Any.type_url");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 1, this->type_url(), target);
+ }
+
+ // optional bytes value = 2;
+ if (this->value().size() > 0) {
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
+ 2, this->value(), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Any)
+ return target;
+}
+
+int Any::ByteSize() const {
+ int total_size = 0;
+
+ // optional string type_url = 1;
+ if (this->type_url().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->type_url());
+ }
+
+ // optional bytes value = 2;
+ if (this->value().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::BytesSize(
+ this->value());
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void Any::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const Any* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Any>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void Any::MergeFrom(const Any& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from.type_url().size() > 0) {
+
+ type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_);
+ }
+ if (from.value().size() > 0) {
+
+ value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_);
+ }
+}
+
+void Any::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void Any::CopyFrom(const Any& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Any::IsInitialized() const {
+
+ return true;
+}
+
+void Any::Swap(Any* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void Any::InternalSwap(Any* other) {
+ type_url_.Swap(&other->type_url_);
+ value_.Swap(&other->value_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Any::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = Any_descriptor_;
+ metadata.reflection = Any_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Any
+
+// optional string type_url = 1;
+void Any::clear_type_url() {
+ type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Any::type_url() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
+ return type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Any::set_type_url(const ::std::string& value) {
+
+ type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
+}
+ void Any::set_type_url(const char* value) {
+
+ type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Any.type_url)
+}
+ void Any::set_type_url(const char* value, size_t size) {
+
+ type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.type_url)
+}
+ ::std::string* Any::mutable_type_url() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url)
+ return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Any::release_type_url() {
+
+ return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Any::set_allocated_type_url(::std::string* type_url) {
+ if (type_url != NULL) {
+
+ } else {
+
+ }
+ type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_url);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url)
+}
+
+// optional bytes value = 2;
+void Any::clear_value() {
+ value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Any::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Any.value)
+ return value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Any::set_value(const ::std::string& value) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Any.value)
+}
+ void Any::set_value(const char* value) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Any.value)
+}
+ void Any::set_value(const void* value, size_t size) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.value)
+}
+ ::std::string* Any::mutable_value() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Any.value)
+ return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Any::release_value() {
+
+ return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Any::set_allocated_value(::std::string* value) {
+ if (value != NULL) {
+
+ } else {
+
+ }
+ value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h
new file mode 100644
index 00000000..c324c4af
--- /dev/null
+++ b/src/google/protobuf/any.pb.h
@@ -0,0 +1,250 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/any.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+#include "google/protobuf/any.h"
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fany_2eproto();
+
+class Any;
+
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message {
+ public:
+ Any();
+ virtual ~Any();
+
+ Any(const Any& from);
+
+ inline Any& operator=(const Any& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const Any& default_instance();
+
+ // implements Any -----------------------------------------------
+
+ void PackFrom(const ::google::protobuf::Message& message);
+ bool UnpackTo(::google::protobuf::Message* message) const;
+ template<typename T> bool Is() const {
+ return _any_metadata_.Is<T>();
+ }
+
+ void Swap(Any* other);
+
+ // implements Message ----------------------------------------------
+
+ inline Any* New() const { return New(NULL); }
+
+ Any* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const Any& from);
+ void MergeFrom(const Any& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(Any* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional string type_url = 1;
+ void clear_type_url();
+ static const int kTypeUrlFieldNumber = 1;
+ const ::std::string& type_url() const;
+ void set_type_url(const ::std::string& value);
+ void set_type_url(const char* value);
+ void set_type_url(const char* value, size_t size);
+ ::std::string* mutable_type_url();
+ ::std::string* release_type_url();
+ void set_allocated_type_url(::std::string* type_url);
+
+ // optional bytes value = 2;
+ void clear_value();
+ static const int kValueFieldNumber = 2;
+ const ::std::string& value() const;
+ void set_value(const ::std::string& value);
+ void set_value(const char* value);
+ void set_value(const void* value, size_t size);
+ ::std::string* mutable_value();
+ ::std::string* release_value();
+ void set_allocated_value(::std::string* value);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.Any)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::internal::ArenaStringPtr type_url_;
+ ::google::protobuf::internal::ArenaStringPtr value_;
+ mutable int _cached_size_;
+ ::google::protobuf::internal::AnyMetadata _any_metadata_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fany_2eproto();
+
+ void InitAsDefaultInstance();
+ static Any* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// Any
+
+// optional string type_url = 1;
+inline void Any::clear_type_url() {
+ type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Any::type_url() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
+ return type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Any::set_type_url(const ::std::string& value) {
+
+ type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
+}
+inline void Any::set_type_url(const char* value) {
+
+ type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Any.type_url)
+}
+inline void Any::set_type_url(const char* value, size_t size) {
+
+ type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.type_url)
+}
+inline ::std::string* Any::mutable_type_url() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url)
+ return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Any::release_type_url() {
+
+ return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Any::set_allocated_type_url(::std::string* type_url) {
+ if (type_url != NULL) {
+
+ } else {
+
+ }
+ type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_url);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url)
+}
+
+// optional bytes value = 2;
+inline void Any::clear_value() {
+ value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Any::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Any.value)
+ return value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Any::set_value(const ::std::string& value) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Any.value)
+}
+inline void Any::set_value(const char* value) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Any.value)
+}
+inline void Any::set_value(const void* value, size_t size) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.value)
+}
+inline ::std::string* Any::mutable_value() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Any.value)
+ return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Any::release_value() {
+
+ return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Any::set_allocated_value(::std::string* value) {
+ if (value != NULL) {
+
+ } else {
+
+ }
+ value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
+}
+
+#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif // PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED
diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto
new file mode 100644
index 00000000..d3ad3acc
--- /dev/null
+++ b/src/google/protobuf/any.proto
@@ -0,0 +1,104 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+syntax = "proto3";
+
+package google.protobuf;
+
+option java_generate_equals_and_hash = true;
+option java_multiple_files = true;
+option java_outer_classname = "AnyProto";
+option java_package = "com.google.protobuf";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option objc_class_prefix = "GPB";
+
+
+// `Any` contains an arbitrary serialized message along with a URL
+// that describes the type of the serialized message.
+//
+// The proto runtimes and/or compiler will eventually
+// provide utilities to pack/unpack Any values (projected Q1/15).
+//
+// # JSON
+// The JSON representation of an `Any` value uses the regular
+// representation of the deserialized, embedded message, with an
+// additional field `@type` which contains the type URL. Example:
+//
+// package google.profile;
+// message Person {
+// string first_name = 1;
+// string last_name = 2;
+// }
+//
+// {
+// "@type": "type.googleapis.com/google.profile.Person",
+// "firstName": <string>,
+// "lastName": <string>
+// }
+//
+// If the embedded message type is well-known and has a custom JSON
+// representation, that representation will be embedded adding a field
+// `value` which holds the custom JSON in addition to the the `@type`
+// field. Example (for message [google.protobuf.Duration][google.protobuf.Duration]):
+//
+// {
+// "@type": "type.googleapis.com/google.protobuf.Duration",
+// "value": "1.212s"
+// }
+//
+message Any {
+ // A URL/resource name whose content describes the type of the
+ // serialized message.
+ //
+ // For URLs which use the schema `http`, `https`, or no schema, the
+ // following restrictions and interpretations apply:
+ //
+ // * If no schema is provided, `https` is assumed.
+ // * The last segment of the URL's path must represent the fully
+ // qualified name of the type (as in `path/google.protobuf.Duration`).
+ // * An HTTP GET on the URL must yield a [google.protobuf.Type][google.protobuf.Type]
+ // value in binary format, or produce an error.
+ // * Applications are allowed to cache lookup results based on the
+ // URL, or have them precompiled into a binary to avoid any
+ // lookup. Therefore, binary compatibility needs to be preserved
+ // on changes to types. (Use versioned type names to manage
+ // breaking changes.)
+ //
+ // Schemas other than `http`, `https` (or the empty schema) might be
+ // used with implementation specific semantics.
+ //
+ // Types originating from the `google.*` package
+ // namespace should use `type.googleapis.com/full.type.name` (without
+ // schema and path). A type service will eventually become available which
+ // serves those URLs (projected Q2/15).
+ string type_url = 1;
+
+ // Must be valid serialized data of the above specified type.
+ bytes value = 2;
+}
diff --git a/src/google/protobuf/any_test.cc b/src/google/protobuf/any_test.cc
new file mode 100644
index 00000000..1bfaa63d
--- /dev/null
+++ b/src/google/protobuf/any_test.cc
@@ -0,0 +1,89 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/any_test.pb.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+TEST(AnyTest, TestPackAndUnpack) {
+ protobuf_unittest::TestAny submessage;
+ submessage.set_int32_value(12345);
+ protobuf_unittest::TestAny message;
+ message.mutable_any_value()->PackFrom(submessage);
+
+ string data = message.SerializeAsString();
+
+ ASSERT_TRUE(message.ParseFromString(data));
+ EXPECT_TRUE(message.has_any_value());
+ ASSERT_TRUE(message.any_value().UnpackTo(&submessage));
+ EXPECT_EQ(12345, submessage.int32_value());
+}
+
+TEST(AnyTest, TestPackAndUnpackAny) {
+ // We can pack a Any message inside another Any message.
+ protobuf_unittest::TestAny submessage;
+ submessage.set_int32_value(12345);
+ google::protobuf::Any any;
+ any.PackFrom(submessage);
+ protobuf_unittest::TestAny message;
+ message.mutable_any_value()->PackFrom(any);
+
+ string data = message.SerializeAsString();
+
+ ASSERT_TRUE(message.ParseFromString(data));
+ EXPECT_TRUE(message.has_any_value());
+ ASSERT_TRUE(message.any_value().UnpackTo(&any));
+ ASSERT_TRUE(any.UnpackTo(&submessage));
+ EXPECT_EQ(12345, submessage.int32_value());
+}
+
+TEST(AnyTest, TestIs) {
+ protobuf_unittest::TestAny submessage;
+ submessage.set_int32_value(12345);
+ google::protobuf::Any any;
+ any.PackFrom(submessage);
+ ASSERT_TRUE(any.ParseFromString(any.SerializeAsString()));
+ EXPECT_TRUE(any.Is<protobuf_unittest::TestAny>());
+ EXPECT_FALSE(any.Is<google::protobuf::Any>());
+
+ protobuf_unittest::TestAny message;
+ message.mutable_any_value()->PackFrom(any);
+ ASSERT_TRUE(message.ParseFromString(message.SerializeAsString()));
+ EXPECT_FALSE(message.any_value().Is<protobuf_unittest::TestAny>());
+ EXPECT_TRUE(message.any_value().Is<google::protobuf::Any>());
+}
+
+} // namespace
+} // namespace protobuf
+
+} // namespace google
diff --git a/src/google/protobuf/any_test.proto b/src/google/protobuf/any_test.proto
new file mode 100644
index 00000000..0c5b30ba
--- /dev/null
+++ b/src/google/protobuf/any_test.proto
@@ -0,0 +1,41 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package protobuf_unittest;
+
+import "google/protobuf/any.proto";
+
+message TestAny {
+ int32 int32_value = 1;
+ google.protobuf.Any any_value = 2;
+ repeated google.protobuf.Any repeated_any_value = 3;
+}
diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc
new file mode 100644
index 00000000..0feddb31
--- /dev/null
+++ b/src/google/protobuf/api.pb.cc
@@ -0,0 +1,1401 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/api.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "google/protobuf/api.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* Api_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ Api_reflection_ = NULL;
+const ::google::protobuf::Descriptor* Method_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ Method_reflection_ = NULL;
+
+} // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+ const ::google::protobuf::FileDescriptor* file =
+ ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+ "google/protobuf/api.proto");
+ GOOGLE_CHECK(file != NULL);
+ Api_descriptor_ = file->message_type(0);
+ static const int Api_offsets_[5] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, name_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, methods_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, options_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, version_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, source_context_),
+ };
+ Api_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ Api_descriptor_,
+ Api::default_instance_,
+ Api_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(Api),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, _is_default_instance_));
+ Method_descriptor_ = file->message_type(1);
+ static const int Method_offsets_[6] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, name_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, request_type_url_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, request_streaming_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, response_type_url_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, response_streaming_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, options_),
+ };
+ Method_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ Method_descriptor_,
+ Method::default_instance_,
+ Method_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(Method),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+ ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+ &protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ Api_descriptor_, &Api::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ Method_descriptor_, &Method::default_instance());
+}
+
+} // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto() {
+ delete Api::default_instance_;
+ delete Api_reflection_;
+ delete Method::default_instance_;
+ delete Method_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto() {
+ static bool already_here = false;
+ if (already_here) return;
+ already_here = true;
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+ ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+ ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+ "\n\031google/protobuf/api.proto\022\017google.prot"
+ "obuf\032$google/protobuf/source_context.pro"
+ "to\032\032google/protobuf/type.proto\"\260\001\n\003Api\022\014"
+ "\n\004name\030\001 \001(\t\022(\n\007methods\030\002 \003(\0132\027.google.p"
+ "rotobuf.Method\022(\n\007options\030\003 \003(\0132\027.google"
+ ".protobuf.Option\022\017\n\007version\030\004 \001(\t\0226\n\016sou"
+ "rce_context\030\005 \001(\0132\036.google.protobuf.Sour"
+ "ceContext\"\254\001\n\006Method\022\014\n\004name\030\001 \001(\t\022\030\n\020re"
+ "quest_type_url\030\002 \001(\t\022\031\n\021request_streamin"
+ "g\030\003 \001(\010\022\031\n\021response_type_url\030\004 \001(\t\022\032\n\022re"
+ "sponse_streaming\030\005 \001(\010\022(\n\007options\030\006 \003(\0132"
+ "\027.google.protobuf.OptionBH\n\023com.google.p"
+ "rotobufB\010ApiProtoP\001\242\002\003GPB\252\002\036Google.Proto"
+ "buf.WellKnownTypesb\006proto3", 546);
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+ "google/protobuf/api.proto", &protobuf_RegisterTypes);
+ Api::default_instance_ = new Api();
+ Method::default_instance_ = new Method();
+ Api::default_instance_->InitAsDefaultInstance();
+ Method::default_instance_->InitAsDefaultInstance();
+ ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fapi_2eproto {
+ StaticDescriptorInitializer_google_2fprotobuf_2fapi_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+ }
+} static_descriptor_initializer_google_2fprotobuf_2fapi_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+ GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+} // namespace
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int Api::kNameFieldNumber;
+const int Api::kMethodsFieldNumber;
+const int Api::kOptionsFieldNumber;
+const int Api::kVersionFieldNumber;
+const int Api::kSourceContextFieldNumber;
+#endif // !_MSC_VER
+
+Api::Api()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.Api)
+}
+
+void Api::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+ source_context_ = const_cast< ::google::protobuf::SourceContext*>(&::google::protobuf::SourceContext::default_instance());
+}
+
+Api::Api(const Api& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.Api)
+}
+
+void Api::SharedCtor() {
+ _is_default_instance_ = false;
+ ::google::protobuf::internal::GetEmptyString();
+ _cached_size_ = 0;
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ version_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ source_context_ = NULL;
+}
+
+Api::~Api() {
+ // @@protoc_insertion_point(destructor:google.protobuf.Api)
+ SharedDtor();
+}
+
+void Api::SharedDtor() {
+ name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ version_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (this != default_instance_) {
+ delete source_context_;
+ }
+}
+
+void Api::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Api::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Api_descriptor_;
+}
+
+const Api& Api::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+ return *default_instance_;
+}
+
+Api* Api::default_instance_ = NULL;
+
+Api* Api::New(::google::protobuf::Arena* arena) const {
+ Api* n = new Api;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void Api::Clear() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+ source_context_ = NULL;
+ methods_.Clear();
+ options_.Clear();
+}
+
+bool Api::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.Api)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional string name = 1;
+ case 1: {
+ if (tag == 10) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.Api.name");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(18)) goto parse_methods;
+ break;
+ }
+
+ // repeated .google.protobuf.Method methods = 2;
+ case 2: {
+ if (tag == 18) {
+ parse_methods:
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_methods:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ input, add_methods()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(18)) goto parse_loop_methods;
+ if (input->ExpectTag(26)) goto parse_loop_options;
+ input->UnsafeDecrementRecursionDepth();
+ break;
+ }
+
+ // repeated .google.protobuf.Option options = 3;
+ case 3: {
+ if (tag == 26) {
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ input, add_options()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(26)) goto parse_loop_options;
+ input->UnsafeDecrementRecursionDepth();
+ if (input->ExpectTag(34)) goto parse_version;
+ break;
+ }
+
+ // optional string version = 4;
+ case 4: {
+ if (tag == 34) {
+ parse_version:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_version()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->version().data(), this->version().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.Api.version");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(42)) goto parse_source_context;
+ break;
+ }
+
+ // optional .google.protobuf.SourceContext source_context = 5;
+ case 5: {
+ if (tag == 42) {
+ parse_source_context:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_source_context()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.Api)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.Api)
+ return false;
+#undef DO_
+}
+
+void Api::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.Api)
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Api.name");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 1, this->name(), output);
+ }
+
+ // repeated .google.protobuf.Method methods = 2;
+ for (unsigned int i = 0, n = this->methods_size(); i < n; i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 2, this->methods(i), output);
+ }
+
+ // repeated .google.protobuf.Option options = 3;
+ for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 3, this->options(i), output);
+ }
+
+ // optional string version = 4;
+ if (this->version().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->version().data(), this->version().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Api.version");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 4, this->version(), output);
+ }
+
+ // optional .google.protobuf.SourceContext source_context = 5;
+ if (this->has_source_context()) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 5, *this->source_context_, output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.Api)
+}
+
+::google::protobuf::uint8* Api::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Api)
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Api.name");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 1, this->name(), target);
+ }
+
+ // repeated .google.protobuf.Method methods = 2;
+ for (unsigned int i = 0, n = this->methods_size(); i < n; i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 2, this->methods(i), target);
+ }
+
+ // repeated .google.protobuf.Option options = 3;
+ for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 3, this->options(i), target);
+ }
+
+ // optional string version = 4;
+ if (this->version().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->version().data(), this->version().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Api.version");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 4, this->version(), target);
+ }
+
+ // optional .google.protobuf.SourceContext source_context = 5;
+ if (this->has_source_context()) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 5, *this->source_context_, target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Api)
+ return target;
+}
+
+int Api::ByteSize() const {
+ int total_size = 0;
+
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->name());
+ }
+
+ // optional string version = 4;
+ if (this->version().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->version());
+ }
+
+ // optional .google.protobuf.SourceContext source_context = 5;
+ if (this->has_source_context()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ *this->source_context_);
+ }
+
+ // repeated .google.protobuf.Method methods = 2;
+ total_size += 1 * this->methods_size();
+ for (int i = 0; i < this->methods_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->methods(i));
+ }
+
+ // repeated .google.protobuf.Option options = 3;
+ total_size += 1 * this->options_size();
+ for (int i = 0; i < this->options_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->options(i));
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void Api::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const Api* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Api>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void Api::MergeFrom(const Api& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ methods_.MergeFrom(from.methods_);
+ options_.MergeFrom(from.options_);
+ if (from.name().size() > 0) {
+
+ name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+ }
+ if (from.version().size() > 0) {
+
+ version_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.version_);
+ }
+ if (from.has_source_context()) {
+ mutable_source_context()->::google::protobuf::SourceContext::MergeFrom(from.source_context());
+ }
+}
+
+void Api::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void Api::CopyFrom(const Api& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Api::IsInitialized() const {
+
+ return true;
+}
+
+void Api::Swap(Api* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void Api::InternalSwap(Api* other) {
+ name_.Swap(&other->name_);
+ methods_.UnsafeArenaSwap(&other->methods_);
+ options_.UnsafeArenaSwap(&other->options_);
+ version_.Swap(&other->version_);
+ std::swap(source_context_, other->source_context_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Api::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = Api_descriptor_;
+ metadata.reflection = Api_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Api
+
+// optional string name = 1;
+void Api::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Api::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Api.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Api::set_name(const ::std::string& value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Api.name)
+}
+ void Api::set_name(const char* value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Api.name)
+}
+ void Api::set_name(const char* value, size_t size) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.name)
+}
+ ::std::string* Api::mutable_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Api.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Api::release_name() {
+
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Api::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+
+ } else {
+
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.name)
+}
+
+// repeated .google.protobuf.Method methods = 2;
+int Api::methods_size() const {
+ return methods_.size();
+}
+void Api::clear_methods() {
+ methods_.Clear();
+}
+ const ::google::protobuf::Method& Api::methods(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Api.methods)
+ return methods_.Get(index);
+}
+ ::google::protobuf::Method* Api::mutable_methods(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Api.methods)
+ return methods_.Mutable(index);
+}
+ ::google::protobuf::Method* Api::add_methods() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Api.methods)
+ return methods_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >&
+Api::methods() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Api.methods)
+ return methods_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >*
+Api::mutable_methods() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.methods)
+ return &methods_;
+}
+
+// repeated .google.protobuf.Option options = 3;
+int Api::options_size() const {
+ return options_.size();
+}
+void Api::clear_options() {
+ options_.Clear();
+}
+ const ::google::protobuf::Option& Api::options(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Api.options)
+ return options_.Get(index);
+}
+ ::google::protobuf::Option* Api::mutable_options(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Api.options)
+ return options_.Mutable(index);
+}
+ ::google::protobuf::Option* Api::add_options() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Api.options)
+ return options_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Api::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Api.options)
+ return options_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Api::mutable_options() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.options)
+ return &options_;
+}
+
+// optional string version = 4;
+void Api::clear_version() {
+ version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Api::version() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Api.version)
+ return version_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Api::set_version(const ::std::string& value) {
+
+ version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Api.version)
+}
+ void Api::set_version(const char* value) {
+
+ version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Api.version)
+}
+ void Api::set_version(const char* value, size_t size) {
+
+ version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.version)
+}
+ ::std::string* Api::mutable_version() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Api.version)
+ return version_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Api::release_version() {
+
+ return version_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Api::set_allocated_version(::std::string* version) {
+ if (version != NULL) {
+
+ } else {
+
+ }
+ version_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), version);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.version)
+}
+
+// optional .google.protobuf.SourceContext source_context = 5;
+bool Api::has_source_context() const {
+ return !_is_default_instance_ && source_context_ != NULL;
+}
+void Api::clear_source_context() {
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+ source_context_ = NULL;
+}
+ const ::google::protobuf::SourceContext& Api::source_context() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Api.source_context)
+ return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
+}
+ ::google::protobuf::SourceContext* Api::mutable_source_context() {
+
+ if (source_context_ == NULL) {
+ source_context_ = new ::google::protobuf::SourceContext;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Api.source_context)
+ return source_context_;
+}
+ ::google::protobuf::SourceContext* Api::release_source_context() {
+
+ ::google::protobuf::SourceContext* temp = source_context_;
+ source_context_ = NULL;
+ return temp;
+}
+ void Api::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
+ delete source_context_;
+ source_context_ = source_context;
+ if (source_context) {
+
+ } else {
+
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.source_context)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int Method::kNameFieldNumber;
+const int Method::kRequestTypeUrlFieldNumber;
+const int Method::kRequestStreamingFieldNumber;
+const int Method::kResponseTypeUrlFieldNumber;
+const int Method::kResponseStreamingFieldNumber;
+const int Method::kOptionsFieldNumber;
+#endif // !_MSC_VER
+
+Method::Method()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.Method)
+}
+
+void Method::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+Method::Method(const Method& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.Method)
+}
+
+void Method::SharedCtor() {
+ _is_default_instance_ = false;
+ ::google::protobuf::internal::GetEmptyString();
+ _cached_size_ = 0;
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ request_type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ request_streaming_ = false;
+ response_type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ response_streaming_ = false;
+}
+
+Method::~Method() {
+ // @@protoc_insertion_point(destructor:google.protobuf.Method)
+ SharedDtor();
+}
+
+void Method::SharedDtor() {
+ name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ request_type_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ response_type_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (this != default_instance_) {
+ }
+}
+
+void Method::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Method::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Method_descriptor_;
+}
+
+const Method& Method::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+ return *default_instance_;
+}
+
+Method* Method::default_instance_ = NULL;
+
+Method* Method::New(::google::protobuf::Arena* arena) const {
+ Method* n = new Method;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void Method::Clear() {
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<Method*>(16)->f)
+
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+ ZR_(request_streaming_, response_streaming_);
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ request_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ response_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+
+#undef ZR_HELPER_
+#undef ZR_
+
+ options_.Clear();
+}
+
+bool Method::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.Method)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional string name = 1;
+ case 1: {
+ if (tag == 10) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.Method.name");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(18)) goto parse_request_type_url;
+ break;
+ }
+
+ // optional string request_type_url = 2;
+ case 2: {
+ if (tag == 18) {
+ parse_request_type_url:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_request_type_url()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->request_type_url().data(), this->request_type_url().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.Method.request_type_url");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(24)) goto parse_request_streaming;
+ break;
+ }
+
+ // optional bool request_streaming = 3;
+ case 3: {
+ if (tag == 24) {
+ parse_request_streaming:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &request_streaming_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(34)) goto parse_response_type_url;
+ break;
+ }
+
+ // optional string response_type_url = 4;
+ case 4: {
+ if (tag == 34) {
+ parse_response_type_url:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_response_type_url()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->response_type_url().data(), this->response_type_url().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.Method.response_type_url");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(40)) goto parse_response_streaming;
+ break;
+ }
+
+ // optional bool response_streaming = 5;
+ case 5: {
+ if (tag == 40) {
+ parse_response_streaming:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &response_streaming_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(50)) goto parse_options;
+ break;
+ }
+
+ // repeated .google.protobuf.Option options = 6;
+ case 6: {
+ if (tag == 50) {
+ parse_options:
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ input, add_options()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(50)) goto parse_loop_options;
+ input->UnsafeDecrementRecursionDepth();
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.Method)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.Method)
+ return false;
+#undef DO_
+}
+
+void Method::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.Method)
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Method.name");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 1, this->name(), output);
+ }
+
+ // optional string request_type_url = 2;
+ if (this->request_type_url().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->request_type_url().data(), this->request_type_url().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Method.request_type_url");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 2, this->request_type_url(), output);
+ }
+
+ // optional bool request_streaming = 3;
+ if (this->request_streaming() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->request_streaming(), output);
+ }
+
+ // optional string response_type_url = 4;
+ if (this->response_type_url().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->response_type_url().data(), this->response_type_url().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Method.response_type_url");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 4, this->response_type_url(), output);
+ }
+
+ // optional bool response_streaming = 5;
+ if (this->response_streaming() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(5, this->response_streaming(), output);
+ }
+
+ // repeated .google.protobuf.Option options = 6;
+ for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 6, this->options(i), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.Method)
+}
+
+::google::protobuf::uint8* Method::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Method)
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Method.name");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 1, this->name(), target);
+ }
+
+ // optional string request_type_url = 2;
+ if (this->request_type_url().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->request_type_url().data(), this->request_type_url().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Method.request_type_url");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 2, this->request_type_url(), target);
+ }
+
+ // optional bool request_streaming = 3;
+ if (this->request_streaming() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->request_streaming(), target);
+ }
+
+ // optional string response_type_url = 4;
+ if (this->response_type_url().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->response_type_url().data(), this->response_type_url().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Method.response_type_url");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 4, this->response_type_url(), target);
+ }
+
+ // optional bool response_streaming = 5;
+ if (this->response_streaming() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(5, this->response_streaming(), target);
+ }
+
+ // repeated .google.protobuf.Option options = 6;
+ for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 6, this->options(i), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Method)
+ return target;
+}
+
+int Method::ByteSize() const {
+ int total_size = 0;
+
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->name());
+ }
+
+ // optional string request_type_url = 2;
+ if (this->request_type_url().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->request_type_url());
+ }
+
+ // optional bool request_streaming = 3;
+ if (this->request_streaming() != 0) {
+ total_size += 1 + 1;
+ }
+
+ // optional string response_type_url = 4;
+ if (this->response_type_url().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->response_type_url());
+ }
+
+ // optional bool response_streaming = 5;
+ if (this->response_streaming() != 0) {
+ total_size += 1 + 1;
+ }
+
+ // repeated .google.protobuf.Option options = 6;
+ total_size += 1 * this->options_size();
+ for (int i = 0; i < this->options_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->options(i));
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void Method::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const Method* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Method>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void Method::MergeFrom(const Method& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ options_.MergeFrom(from.options_);
+ if (from.name().size() > 0) {
+
+ name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+ }
+ if (from.request_type_url().size() > 0) {
+
+ request_type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.request_type_url_);
+ }
+ if (from.request_streaming() != 0) {
+ set_request_streaming(from.request_streaming());
+ }
+ if (from.response_type_url().size() > 0) {
+
+ response_type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.response_type_url_);
+ }
+ if (from.response_streaming() != 0) {
+ set_response_streaming(from.response_streaming());
+ }
+}
+
+void Method::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void Method::CopyFrom(const Method& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Method::IsInitialized() const {
+
+ return true;
+}
+
+void Method::Swap(Method* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void Method::InternalSwap(Method* other) {
+ name_.Swap(&other->name_);
+ request_type_url_.Swap(&other->request_type_url_);
+ std::swap(request_streaming_, other->request_streaming_);
+ response_type_url_.Swap(&other->response_type_url_);
+ std::swap(response_streaming_, other->response_streaming_);
+ options_.UnsafeArenaSwap(&other->options_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Method::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = Method_descriptor_;
+ metadata.reflection = Method_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Method
+
+// optional string name = 1;
+void Method::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Method::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Method.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Method::set_name(const ::std::string& value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Method.name)
+}
+ void Method::set_name(const char* value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Method.name)
+}
+ void Method::set_name(const char* value, size_t size) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.name)
+}
+ ::std::string* Method::mutable_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Method.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Method::release_name() {
+
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Method::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+
+ } else {
+
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.name)
+}
+
+// optional string request_type_url = 2;
+void Method::clear_request_type_url() {
+ request_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Method::request_type_url() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Method.request_type_url)
+ return request_type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Method::set_request_type_url(const ::std::string& value) {
+
+ request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Method.request_type_url)
+}
+ void Method::set_request_type_url(const char* value) {
+
+ request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Method.request_type_url)
+}
+ void Method::set_request_type_url(const char* value, size_t size) {
+
+ request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.request_type_url)
+}
+ ::std::string* Method::mutable_request_type_url() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Method.request_type_url)
+ return request_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Method::release_request_type_url() {
+
+ return request_type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Method::set_allocated_request_type_url(::std::string* request_type_url) {
+ if (request_type_url != NULL) {
+
+ } else {
+
+ }
+ request_type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), request_type_url);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.request_type_url)
+}
+
+// optional bool request_streaming = 3;
+void Method::clear_request_streaming() {
+ request_streaming_ = false;
+}
+ bool Method::request_streaming() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Method.request_streaming)
+ return request_streaming_;
+}
+ void Method::set_request_streaming(bool value) {
+
+ request_streaming_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Method.request_streaming)
+}
+
+// optional string response_type_url = 4;
+void Method::clear_response_type_url() {
+ response_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Method::response_type_url() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Method.response_type_url)
+ return response_type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Method::set_response_type_url(const ::std::string& value) {
+
+ response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Method.response_type_url)
+}
+ void Method::set_response_type_url(const char* value) {
+
+ response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Method.response_type_url)
+}
+ void Method::set_response_type_url(const char* value, size_t size) {
+
+ response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.response_type_url)
+}
+ ::std::string* Method::mutable_response_type_url() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Method.response_type_url)
+ return response_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Method::release_response_type_url() {
+
+ return response_type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Method::set_allocated_response_type_url(::std::string* response_type_url) {
+ if (response_type_url != NULL) {
+
+ } else {
+
+ }
+ response_type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), response_type_url);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.response_type_url)
+}
+
+// optional bool response_streaming = 5;
+void Method::clear_response_streaming() {
+ response_streaming_ = false;
+}
+ bool Method::response_streaming() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Method.response_streaming)
+ return response_streaming_;
+}
+ void Method::set_response_streaming(bool value) {
+
+ response_streaming_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Method.response_streaming)
+}
+
+// repeated .google.protobuf.Option options = 6;
+int Method::options_size() const {
+ return options_.size();
+}
+void Method::clear_options() {
+ options_.Clear();
+}
+ const ::google::protobuf::Option& Method::options(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Method.options)
+ return options_.Get(index);
+}
+ ::google::protobuf::Option* Method::mutable_options(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Method.options)
+ return options_.Mutable(index);
+}
+ ::google::protobuf::Option* Method::add_options() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Method.options)
+ return options_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Method::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Method.options)
+ return options_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Method::mutable_options() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Method.options)
+ return &options_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h
new file mode 100644
index 00000000..985adc5d
--- /dev/null
+++ b/src/google/protobuf/api.pb.h
@@ -0,0 +1,703 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/api.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fapi_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fapi_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+#include "google/protobuf/source_context.pb.h"
+#include "google/protobuf/type.pb.h"
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto();
+
+class Api;
+class Method;
+
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message {
+ public:
+ Api();
+ virtual ~Api();
+
+ Api(const Api& from);
+
+ inline Api& operator=(const Api& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const Api& default_instance();
+
+ void Swap(Api* other);
+
+ // implements Message ----------------------------------------------
+
+ inline Api* New() const { return New(NULL); }
+
+ Api* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const Api& from);
+ void MergeFrom(const Api& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(Api* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional string name = 1;
+ void clear_name();
+ static const int kNameFieldNumber = 1;
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
+
+ // repeated .google.protobuf.Method methods = 2;
+ int methods_size() const;
+ void clear_methods();
+ static const int kMethodsFieldNumber = 2;
+ const ::google::protobuf::Method& methods(int index) const;
+ ::google::protobuf::Method* mutable_methods(int index);
+ ::google::protobuf::Method* add_methods();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >&
+ methods() const;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >*
+ mutable_methods();
+
+ // repeated .google.protobuf.Option options = 3;
+ int options_size() const;
+ void clear_options();
+ static const int kOptionsFieldNumber = 3;
+ const ::google::protobuf::Option& options(int index) const;
+ ::google::protobuf::Option* mutable_options(int index);
+ ::google::protobuf::Option* add_options();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+ options() const;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+ mutable_options();
+
+ // optional string version = 4;
+ void clear_version();
+ static const int kVersionFieldNumber = 4;
+ const ::std::string& version() const;
+ void set_version(const ::std::string& value);
+ void set_version(const char* value);
+ void set_version(const char* value, size_t size);
+ ::std::string* mutable_version();
+ ::std::string* release_version();
+ void set_allocated_version(::std::string* version);
+
+ // optional .google.protobuf.SourceContext source_context = 5;
+ bool has_source_context() const;
+ void clear_source_context();
+ static const int kSourceContextFieldNumber = 5;
+ const ::google::protobuf::SourceContext& source_context() const;
+ ::google::protobuf::SourceContext* mutable_source_context();
+ ::google::protobuf::SourceContext* release_source_context();
+ void set_allocated_source_context(::google::protobuf::SourceContext* source_context);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.Api)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::internal::ArenaStringPtr name_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method > methods_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
+ ::google::protobuf::internal::ArenaStringPtr version_;
+ ::google::protobuf::SourceContext* source_context_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto();
+
+ void InitAsDefaultInstance();
+ static Api* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message {
+ public:
+ Method();
+ virtual ~Method();
+
+ Method(const Method& from);
+
+ inline Method& operator=(const Method& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const Method& default_instance();
+
+ void Swap(Method* other);
+
+ // implements Message ----------------------------------------------
+
+ inline Method* New() const { return New(NULL); }
+
+ Method* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const Method& from);
+ void MergeFrom(const Method& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(Method* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional string name = 1;
+ void clear_name();
+ static const int kNameFieldNumber = 1;
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
+
+ // optional string request_type_url = 2;
+ void clear_request_type_url();
+ static const int kRequestTypeUrlFieldNumber = 2;
+ const ::std::string& request_type_url() const;
+ void set_request_type_url(const ::std::string& value);
+ void set_request_type_url(const char* value);
+ void set_request_type_url(const char* value, size_t size);
+ ::std::string* mutable_request_type_url();
+ ::std::string* release_request_type_url();
+ void set_allocated_request_type_url(::std::string* request_type_url);
+
+ // optional bool request_streaming = 3;
+ void clear_request_streaming();
+ static const int kRequestStreamingFieldNumber = 3;
+ bool request_streaming() const;
+ void set_request_streaming(bool value);
+
+ // optional string response_type_url = 4;
+ void clear_response_type_url();
+ static const int kResponseTypeUrlFieldNumber = 4;
+ const ::std::string& response_type_url() const;
+ void set_response_type_url(const ::std::string& value);
+ void set_response_type_url(const char* value);
+ void set_response_type_url(const char* value, size_t size);
+ ::std::string* mutable_response_type_url();
+ ::std::string* release_response_type_url();
+ void set_allocated_response_type_url(::std::string* response_type_url);
+
+ // optional bool response_streaming = 5;
+ void clear_response_streaming();
+ static const int kResponseStreamingFieldNumber = 5;
+ bool response_streaming() const;
+ void set_response_streaming(bool value);
+
+ // repeated .google.protobuf.Option options = 6;
+ int options_size() const;
+ void clear_options();
+ static const int kOptionsFieldNumber = 6;
+ const ::google::protobuf::Option& options(int index) const;
+ ::google::protobuf::Option* mutable_options(int index);
+ ::google::protobuf::Option* add_options();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+ options() const;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+ mutable_options();
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.Method)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::internal::ArenaStringPtr name_;
+ ::google::protobuf::internal::ArenaStringPtr request_type_url_;
+ ::google::protobuf::internal::ArenaStringPtr response_type_url_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
+ bool request_streaming_;
+ bool response_streaming_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto();
+
+ void InitAsDefaultInstance();
+ static Method* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// Api
+
+// optional string name = 1;
+inline void Api::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Api::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Api.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Api::set_name(const ::std::string& value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Api.name)
+}
+inline void Api::set_name(const char* value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Api.name)
+}
+inline void Api::set_name(const char* value, size_t size) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.name)
+}
+inline ::std::string* Api::mutable_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Api.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Api::release_name() {
+
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Api::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+
+ } else {
+
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.name)
+}
+
+// repeated .google.protobuf.Method methods = 2;
+inline int Api::methods_size() const {
+ return methods_.size();
+}
+inline void Api::clear_methods() {
+ methods_.Clear();
+}
+inline const ::google::protobuf::Method& Api::methods(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Api.methods)
+ return methods_.Get(index);
+}
+inline ::google::protobuf::Method* Api::mutable_methods(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Api.methods)
+ return methods_.Mutable(index);
+}
+inline ::google::protobuf::Method* Api::add_methods() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Api.methods)
+ return methods_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >&
+Api::methods() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Api.methods)
+ return methods_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >*
+Api::mutable_methods() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.methods)
+ return &methods_;
+}
+
+// repeated .google.protobuf.Option options = 3;
+inline int Api::options_size() const {
+ return options_.size();
+}
+inline void Api::clear_options() {
+ options_.Clear();
+}
+inline const ::google::protobuf::Option& Api::options(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Api.options)
+ return options_.Get(index);
+}
+inline ::google::protobuf::Option* Api::mutable_options(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Api.options)
+ return options_.Mutable(index);
+}
+inline ::google::protobuf::Option* Api::add_options() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Api.options)
+ return options_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Api::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Api.options)
+ return options_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Api::mutable_options() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.options)
+ return &options_;
+}
+
+// optional string version = 4;
+inline void Api::clear_version() {
+ version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Api::version() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Api.version)
+ return version_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Api::set_version(const ::std::string& value) {
+
+ version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Api.version)
+}
+inline void Api::set_version(const char* value) {
+
+ version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Api.version)
+}
+inline void Api::set_version(const char* value, size_t size) {
+
+ version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.version)
+}
+inline ::std::string* Api::mutable_version() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Api.version)
+ return version_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Api::release_version() {
+
+ return version_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Api::set_allocated_version(::std::string* version) {
+ if (version != NULL) {
+
+ } else {
+
+ }
+ version_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), version);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.version)
+}
+
+// optional .google.protobuf.SourceContext source_context = 5;
+inline bool Api::has_source_context() const {
+ return !_is_default_instance_ && source_context_ != NULL;
+}
+inline void Api::clear_source_context() {
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+ source_context_ = NULL;
+}
+inline const ::google::protobuf::SourceContext& Api::source_context() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Api.source_context)
+ return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
+}
+inline ::google::protobuf::SourceContext* Api::mutable_source_context() {
+
+ if (source_context_ == NULL) {
+ source_context_ = new ::google::protobuf::SourceContext;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Api.source_context)
+ return source_context_;
+}
+inline ::google::protobuf::SourceContext* Api::release_source_context() {
+
+ ::google::protobuf::SourceContext* temp = source_context_;
+ source_context_ = NULL;
+ return temp;
+}
+inline void Api::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
+ delete source_context_;
+ source_context_ = source_context;
+ if (source_context) {
+
+ } else {
+
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.source_context)
+}
+
+// -------------------------------------------------------------------
+
+// Method
+
+// optional string name = 1;
+inline void Method::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Method::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Method.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Method::set_name(const ::std::string& value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Method.name)
+}
+inline void Method::set_name(const char* value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Method.name)
+}
+inline void Method::set_name(const char* value, size_t size) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.name)
+}
+inline ::std::string* Method::mutable_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Method.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Method::release_name() {
+
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Method::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+
+ } else {
+
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.name)
+}
+
+// optional string request_type_url = 2;
+inline void Method::clear_request_type_url() {
+ request_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Method::request_type_url() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Method.request_type_url)
+ return request_type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Method::set_request_type_url(const ::std::string& value) {
+
+ request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Method.request_type_url)
+}
+inline void Method::set_request_type_url(const char* value) {
+
+ request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Method.request_type_url)
+}
+inline void Method::set_request_type_url(const char* value, size_t size) {
+
+ request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.request_type_url)
+}
+inline ::std::string* Method::mutable_request_type_url() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Method.request_type_url)
+ return request_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Method::release_request_type_url() {
+
+ return request_type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Method::set_allocated_request_type_url(::std::string* request_type_url) {
+ if (request_type_url != NULL) {
+
+ } else {
+
+ }
+ request_type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), request_type_url);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.request_type_url)
+}
+
+// optional bool request_streaming = 3;
+inline void Method::clear_request_streaming() {
+ request_streaming_ = false;
+}
+inline bool Method::request_streaming() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Method.request_streaming)
+ return request_streaming_;
+}
+inline void Method::set_request_streaming(bool value) {
+
+ request_streaming_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Method.request_streaming)
+}
+
+// optional string response_type_url = 4;
+inline void Method::clear_response_type_url() {
+ response_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Method::response_type_url() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Method.response_type_url)
+ return response_type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Method::set_response_type_url(const ::std::string& value) {
+
+ response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Method.response_type_url)
+}
+inline void Method::set_response_type_url(const char* value) {
+
+ response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Method.response_type_url)
+}
+inline void Method::set_response_type_url(const char* value, size_t size) {
+
+ response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.response_type_url)
+}
+inline ::std::string* Method::mutable_response_type_url() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Method.response_type_url)
+ return response_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Method::release_response_type_url() {
+
+ return response_type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Method::set_allocated_response_type_url(::std::string* response_type_url) {
+ if (response_type_url != NULL) {
+
+ } else {
+
+ }
+ response_type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), response_type_url);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.response_type_url)
+}
+
+// optional bool response_streaming = 5;
+inline void Method::clear_response_streaming() {
+ response_streaming_ = false;
+}
+inline bool Method::response_streaming() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Method.response_streaming)
+ return response_streaming_;
+}
+inline void Method::set_response_streaming(bool value) {
+
+ response_streaming_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Method.response_streaming)
+}
+
+// repeated .google.protobuf.Option options = 6;
+inline int Method::options_size() const {
+ return options_.size();
+}
+inline void Method::clear_options() {
+ options_.Clear();
+}
+inline const ::google::protobuf::Option& Method::options(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Method.options)
+ return options_.Get(index);
+}
+inline ::google::protobuf::Option* Method::mutable_options(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Method.options)
+ return options_.Mutable(index);
+}
+inline ::google::protobuf::Option* Method::add_options() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Method.options)
+ return options_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Method::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Method.options)
+ return options_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Method::mutable_options() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Method.options)
+ return &options_;
+}
+
+#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif // PROTOBUF_google_2fprotobuf_2fapi_2eproto__INCLUDED
diff --git a/src/google/protobuf/api.proto b/src/google/protobuf/api.proto
new file mode 100644
index 00000000..d6c2a8b3
--- /dev/null
+++ b/src/google/protobuf/api.proto
@@ -0,0 +1,106 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+syntax = "proto3";
+
+package google.protobuf;
+
+import "google/protobuf/source_context.proto";
+import "google/protobuf/type.proto";
+
+option java_multiple_files = true;
+option java_outer_classname = "ApiProto";
+option java_package = "com.google.protobuf";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option objc_class_prefix = "GPB";
+
+
+// Api is a light-weight descriptor for a protocol buffer service.
+message Api {
+ // The fully qualified name of this api, including package name
+ // followed by the api's simple name.
+ string name = 1;
+
+ // The methods of this api, in unspecified order.
+ repeated Method methods = 2;
+
+ // Any metadata attached to the API.
+ repeated Option options = 3;
+
+ // A version string for this api. If specified, must have the form
+ // `major-version.minor-version`, as in `1.10`. If the minor version
+ // is omitted, it defaults to zero. If the entire version field is
+ // empty, the major version is derived from the package name, as
+ // outlined below. If the field is not empty, the version in the
+ // package name will be verified to be consistent with what is
+ // provided here.
+ //
+ // The versioning schema uses [semantic
+ // versioning](http://semver.org) where the major version number
+ // indicates a breaking change and the minor version an additive,
+ // non-breaking change. Both version numbers are signals to users
+ // what to expect from different versions, and should be carefully
+ // chosen based on the product plan.
+ //
+ // The major version is also reflected in the package name of the
+ // API, which must end in `v<major-version>`, as in
+ // `google.feature.v1`. For major versions 0 and 1, the suffix can
+ // be omitted. Zero major versions must only be used for
+ // experimental, none-GA apis.
+ //
+ // See also: [design doc](http://go/api-versioning).
+ //
+ //
+ string version = 4;
+
+ // Source context for the protocol buffer service represented by this
+ // message.
+ SourceContext source_context = 5;
+}
+
+// Method represents a method of an api.
+message Method {
+ // The simple name of this method.
+ string name = 1;
+
+ // A URL of the input message type.
+ string request_type_url = 2;
+
+ // If true, the request is streamed.
+ bool request_streaming = 3;
+
+ // The URL of the output message type.
+ string response_type_url = 4;
+
+ // If true, the response is streamed.
+ bool response_streaming = 5;
+
+ // Any metadata attached to the method.
+ repeated Option options = 6;
+}
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index 18536781..ed1c5ef2 100644..100755
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -43,39 +43,63 @@ Arena::ThreadCache& Arena::thread_cache() {
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL };
return thread_cache_;
}
+#elif defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
+Arena::ThreadCache& Arena::thread_cache() {
+ static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ =
+ new internal::ThreadLocalStorage<ThreadCache>();
+ return *thread_cache_->Get();
+}
#else
GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL };
#endif
-void Arena::Init(const ArenaOptions& options) {
+void Arena::Init() {
lifecycle_id_ = lifecycle_id_generator_.GetNext();
- start_block_size_ = options.start_block_size;
- max_block_size_ = options.max_block_size;
- block_alloc = options.block_alloc;
- block_dealloc = options.block_dealloc;
blocks_ = 0;
hint_ = 0;
owns_first_block_ = true;
cleanup_list_ = 0;
- if (options.initial_block != NULL && options.initial_block_size > 0) {
+ if (options_.initial_block != NULL && options_.initial_block_size > 0) {
// Add first unowned block to list.
- Block* first_block = reinterpret_cast<Block*>(options.initial_block);
- first_block->size = options.initial_block_size;
+ Block* first_block = reinterpret_cast<Block*>(options_.initial_block);
+ first_block->size = options_.initial_block_size;
first_block->pos = kHeaderSize;
first_block->next = NULL;
first_block->owner = &first_block->owner;
AddBlock(first_block);
owns_first_block_ = false;
}
+
+ // Call the initialization hook
+ if (options_.on_arena_init != NULL) {
+ hooks_cookie_ = options_.on_arena_init(this);
+ } else {
+ hooks_cookie_ = NULL;
+ }
+}
+
+Arena::~Arena() {
+ uint64 space_allocated = Reset();
+
+ // Call the destruction hook
+ if (options_.on_arena_destruction != NULL) {
+ options_.on_arena_destruction(this, hooks_cookie_, space_allocated);
+ }
}
uint64 Arena::Reset() {
CleanupList();
- uint64 space_used = FreeBlocks();
+ uint64 space_allocated = FreeBlocks();
// Invalidate any ThreadCaches pointing to any blocks we just destroyed.
lifecycle_id_ = lifecycle_id_generator_.GetNext();
- return space_used;
+
+ // Call the reset hook
+ if (options_.on_arena_reset != NULL) {
+ options_.on_arena_reset(this, hooks_cookie_, space_allocated);
+ }
+
+ return space_allocated;
}
Arena::Block* Arena::NewBlock(void* me, Block* my_last_block, size_t n,
@@ -93,7 +117,7 @@ Arena::Block* Arena::NewBlock(void* me, Block* my_last_block, size_t n,
size = kHeaderSize + n;
}
- Block* b = reinterpret_cast<Block*>(block_alloc(size));
+ Block* b = reinterpret_cast<Block*>(options_.block_alloc(size));
b->pos = kHeaderSize + n;
b->size = size;
if (b->avail() == 0) {
@@ -130,10 +154,16 @@ void Arena::AddListNode(void* elem, void (*cleanup)(void*)) {
reinterpret_cast<google::protobuf::internal::AtomicWord>(node)));
}
-void* Arena::AllocateAligned(size_t n) {
+void* Arena::AllocateAligned(const std::type_info* allocated, size_t n) {
// Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.)
n = (n + 7) & -8;
+ // Monitor allocation if needed.
+ if (GOOGLE_PREDICT_FALSE(hooks_cookie_ != NULL) &&
+ options_.on_arena_allocation != NULL) {
+ options_.on_arena_allocation(allocated, n, hooks_cookie_);
+ }
+
// If this thread already owns a block in this arena then try to use that.
// This fast path optimizes the case where multiple threads allocate from the
// same arena.
@@ -184,7 +214,7 @@ void* Arena::SlowAlloc(size_t n) {
google::protobuf::internal::NoBarrier_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
return AllocFromBlock(b, n);
}
- b = NewBlock(me, b, n, start_block_size_, max_block_size_);
+ b = NewBlock(me, b, n, options_.start_block_size, options_.max_block_size);
AddBlock(b);
if (b->owner == me) { // If this block can be reused (see NewBlock()).
SetThreadCacheBlock(b);
@@ -192,29 +222,38 @@ void* Arena::SlowAlloc(size_t n) {
return reinterpret_cast<char*>(b) + kHeaderSize;
}
+uint64 Arena::SpaceAllocated() const {
+ uint64 space_allocated = 0;
+ Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
+ while (b != NULL) {
+ space_allocated += (b->size);
+ b = b->next;
+ }
+ return space_allocated;
+}
+
uint64 Arena::SpaceUsed() const {
uint64 space_used = 0;
Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
while (b != NULL) {
- space_used += (b->size);
+ space_used += (b->pos - kHeaderSize);
b = b->next;
}
return space_used;
}
-
uint64 Arena::FreeBlocks() {
- uint64 space_used = 0;
+ uint64 space_allocated = 0;
Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
Block* first_block = NULL;
while (b != NULL) {
- space_used += (b->size);
+ space_allocated += (b->size);
Block* next = b->next;
if (next != NULL) {
- block_dealloc(b, b->size);
+ options_.block_dealloc(b, b->size);
} else {
if (owns_first_block_) {
- block_dealloc(b, b->size);
+ options_.block_dealloc(b, b->size);
} else {
// User passed in the first block, skip free'ing the memory.
first_block = b;
@@ -231,7 +270,7 @@ uint64 Arena::FreeBlocks() {
first_block->owner = &first_block->owner;
AddBlock(first_block);
}
- return space_used;
+ return space_allocated;
}
void Arena::CleanupList() {
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index d0cb163c..51149bae 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -28,15 +28,18 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// This header is logically internal, but is made public because it is used
-// from protocol-compiler-generated code, which may reside in other components.
-
#ifndef GOOGLE_PROTOBUF_ARENA_H__
#define GOOGLE_PROTOBUF_ARENA_H__
-#include <google/protobuf/stubs/common.h>
+#if __cplusplus >= 201103L
+#include <google/protobuf/stubs/type_traits.h>
+#endif
+#include <typeinfo>
+
#include <google/protobuf/stubs/atomic_sequence_num.h>
#include <google/protobuf/stubs/atomicops.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/platform_macros.h>
#include <google/protobuf/stubs/type_traits.h>
namespace google {
@@ -89,19 +92,47 @@ struct ArenaOptions {
// A function pointer to an alloc method that returns memory blocks of size
// requested. By default, it contains a ptr to the malloc function.
+ //
+ // NOTE: block_alloc and dealloc functions are expected to behave like
+ // malloc and free, including Asan poisoning.
void* (*block_alloc)(size_t);
// A function pointer to a dealloc method that takes ownership of the blocks
// from the arena. By default, it contains a ptr to a wrapper function that
// calls free.
void (*block_dealloc)(void*, size_t);
+ // Hooks for adding external functionality such as user-specific metrics
+ // collection, specific debugging abilities, etc.
+ // Init hook may return a pointer to a cookie to be stored in the arena.
+ // reset and destruction hooks will then be called with the same cookie
+ // pointer. This allows us to save an external object per arena instance and
+ // use it on the other hooks (Note: It is just as legal for init to return
+ // NULL and not use the cookie feature).
+ // on_arena_reset and on_arena_destruction also receive the space used in
+ // the arena just before the reset.
+ void* (*on_arena_init)(Arena* arena);
+ void (*on_arena_reset)(Arena* arena, void* cookie, uint64 space_used);
+ void (*on_arena_destruction)(Arena* arena, void* cookie, uint64 space_used);
+
+ // type_info is promised to be static - its lifetime extends to
+ // match program's lifetime (It is given by typeid operator).
+ // Note: typeid(void) will be passed as allocated_type every time we
+ // intentionally want to avoid monitoring an allocation. (i.e. internal
+ // allocations for managing the arena)
+ void (*on_arena_allocation)(const std::type_info* allocated_type,
+ uint64 alloc_size, void* cookie);
+
ArenaOptions()
: start_block_size(kDefaultStartBlockSize),
max_block_size(kDefaultMaxBlockSize),
initial_block(NULL),
initial_block_size(0),
block_alloc(&malloc),
- block_dealloc(&internal::arena_free) {}
+ block_dealloc(&internal::arena_free),
+ on_arena_init(NULL),
+ on_arena_reset(NULL),
+ on_arena_destruction(NULL),
+ on_arena_allocation(NULL) {}
private:
// Constants define default starting block size and max block size for
@@ -110,6 +141,14 @@ struct ArenaOptions {
static const size_t kDefaultMaxBlockSize = 8192;
};
+// Support for non-RTTI environments. (The metrics hooks API uses type
+// information.)
+#ifndef GOOGLE_PROTOBUF_NO_RTTI
+#define RTTI_TYPE_ID(type) (&typeid(type))
+#else
+#define RTTI_TYPE_ID(type) (NULL)
+#endif
+
// Arena allocator. Arena allocation replaces ordinary (heap-based) allocation
// with new/delete, and improves performance by aggregating allocations into
// larger blocks and freeing allocations all at once. Protocol messages are
@@ -119,27 +158,63 @@ struct ArenaOptions {
// This is a thread-safe implementation: multiple threads may allocate from the
// arena concurrently. Destruction is not thread-safe and the destructing
// thread must synchronize with users of the arena first.
+//
+// An arena provides two allocation interfaces: CreateMessage<T>, which works
+// for arena-enabled proto2 message types as well as other types that satisfy
+// the appropriate protocol (described below), and Create<T>, which works for
+// any arbitrary type T. CreateMessage<T> is better when the type T supports it,
+// because this interface (i) passes the arena pointer to the created object so
+// that its sub-objects and internal allocations can use the arena too, and (ii)
+// elides the object's destructor call when possible. Create<T> does not place
+// any special requirements on the type T, and will invoke the object's
+// destructor when the arena is destroyed.
+//
+// The arena message allocation protocol, required by CreateMessage<T>, is as
+// follows:
+//
+// - The type T must have (at least) two constructors: a constructor with no
+// arguments, called when a T is allocated on the heap; and a constructor with
+// a google::protobuf::Arena* argument, called when a T is allocated on an arena. If the
+// second constructor is called with a NULL arena pointer, it must be
+// equivalent to invoking the first (no-argument) constructor.
+//
+// - The type T must have a particular type trait: a nested type
+// |InternalArenaConstructable_|. This is usually a typedef to |void|. If no
+// such type trait exists, then the instantiation CreateMessage<T> will fail
+// to compile.
+//
+// - The type T *may* have the type trait |DestructorSkippable_|. If this type
+// trait is present in the type, then its destructor will not be called if and
+// only if it was passed a non-NULL arena pointer. If this type trait is not
+// present on the type, then its destructor is always called when the
+// containing arena is destroyed.
+//
+// - One- and two-user-argument forms of CreateMessage<T>() also exist that
+// forward these constructor arguments to T's constructor: for example,
+// CreateMessage<T>(Arena*, arg1, arg2) forwards to a constructor T(Arena*,
+// arg1, arg2).
+//
+// This protocol is implemented by all arena-enabled proto2 message classes as
+// well as RepeatedPtrField.
class LIBPROTOBUF_EXPORT Arena {
public:
// Arena constructor taking custom options. See ArenaOptions below for
// descriptions of the options available.
- explicit Arena(const ArenaOptions& options) {
- Init(options);
+ explicit Arena(const ArenaOptions& options) : options_(options) {
+ Init();
}
// Default constructor with sensible default options, tuned for average
// use-cases.
Arena() {
- Init(ArenaOptions());
+ Init();
}
// Destructor deletes all owned heap allocated objects, and destructs objects
// that have non-trivial destructors, except for proto2 message objects whose
// destructors can be skipped. Also, frees all blocks except the initial block
// if it was passed in.
- ~Arena() {
- Reset();
- }
+ ~Arena();
// API to create proto2 message objects on the arena. If the arena passed in
// is NULL, then a heap allocated object is returned. Type T must be a message
@@ -147,8 +222,10 @@ class LIBPROTOBUF_EXPORT Arena {
// compilation error will occur.
//
// RepeatedField and RepeatedPtrField may also be instantiated directly on an
- // arena with this method: they act as "arena-capable message types" for the
- // purposes of the Arena API.
+ // arena with this method.
+ //
+ // This function also accepts any type T that satisfies the arena message
+ // allocation protocol, documented above.
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
static T* CreateMessage(::google::protobuf::Arena* arena) {
if (arena == NULL) {
@@ -158,17 +235,55 @@ class LIBPROTOBUF_EXPORT Arena {
}
}
+ // One-argument form of CreateMessage. This is useful for constructing objects
+ // that implement the arena message construction protocol described above but
+ // take additional constructor arguments.
+ template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static T* CreateMessage(::google::protobuf::Arena* arena, const Arg& arg) {
+ if (arena == NULL) {
+ return new T(NULL, arg);
+ } else {
+ return arena->CreateMessageInternal<T>(static_cast<T*>(0),
+ arg);
+ }
+ }
+
+ // Two-argument form of CreateMessage. This is useful for constructing objects
+ // that implement the arena message construction protocol described above but
+ // take additional constructor arguments.
+ template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static T* CreateMessage(::google::protobuf::Arena* arena,
+ const Arg1& arg1,
+ const Arg2& arg2) {
+ if (arena == NULL) {
+ return new T(NULL, arg1, arg2);
+ } else {
+ return arena->CreateMessageInternal<T>(static_cast<T*>(0),
+ arg1, arg2);
+ }
+ }
+
// API to create any objects on the arena. Note that only the object will
// be created on the arena; the underlying ptrs (in case of a proto2 message)
// will be still heap allocated. Proto messages should usually be allocated
// with CreateMessage<T>() instead.
+ //
+ // Note that even if T satisfies the arena message construction protocol
+ // (InternalArenaConstructable_ trait and optional DestructorSkippable_
+ // trait), as described above, this function does not follow the protocol;
+ // instead, it treats T as a black-box type, just as if it did not have these
+ // traits. Specifically, T's constructor arguments will always be only those
+ // passed to Create<T>() -- no additional arena pointer is implicitly added.
+ // Furthermore, the destructor will always be called at arena destruction time
+ // (unless the destructor is trivial). Hence, from T's point of view, it is as
+ // if the object were allocated on the heap (except that the underlying memory
+ // is obtained from the arena).
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
static T* Create(::google::protobuf::Arena* arena) {
if (arena == NULL) {
return new T();
} else {
- return arena->CreateInternal<T>(
- SkipDeleteList<T>(static_cast<T*>(0)));
+ return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value);
}
}
@@ -178,7 +293,7 @@ class LIBPROTOBUF_EXPORT Arena {
if (arena == NULL) {
return new T(arg);
} else {
- return arena->CreateInternal<T>(SkipDeleteList<T>(static_cast<T*>(0)),
+ return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
arg);
}
}
@@ -189,21 +304,120 @@ class LIBPROTOBUF_EXPORT Arena {
if (arena == NULL) {
return new T(arg1, arg2);
} else {
- return arena->CreateInternal<T>(SkipDeleteList<T>(static_cast<T*>(0)),
- arg1,
- arg2);
+ return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+ arg1, arg2);
+ }
+ }
+
+ // Version of the above with three constructor arguments for the created
+ // object.
+ template <typename T, typename Arg1, typename Arg2, typename Arg3>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+ const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3) {
+ if (arena == NULL) {
+ return new T(arg1, arg2, arg3);
+ } else {
+ return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+ arg1, arg2, arg3);
+ }
+ }
+
+ // Version of the above with four constructor arguments for the created
+ // object.
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+ const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3, const Arg4& arg4) {
+ if (arena == NULL) {
+ return new T(arg1, arg2, arg3, arg4);
+ } else {
+ return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+ arg1, arg2, arg3, arg4);
}
}
- // Create an array of object type T on the arena. Type T must have a trivial
- // constructor, as it will not be invoked when created on the arena.
+ // Version of the above with five constructor arguments for the created
+ // object.
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+ const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3, const Arg4& arg4,
+ const Arg5& arg5) {
+ if (arena == NULL) {
+ return new T(arg1, arg2, arg3, arg4, arg5);
+ } else {
+ return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+ arg1, arg2, arg3, arg4, arg5);
+ }
+ }
+
+ // Version of the above with six constructor arguments for the created
+ // object.
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5, typename Arg6>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+ const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3, const Arg4& arg4,
+ const Arg5& arg5, const Arg6& arg6) {
+ if (arena == NULL) {
+ return new T(arg1, arg2, arg3, arg4, arg5, arg6);
+ } else {
+ return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+ arg1, arg2, arg3, arg4, arg5, arg6);
+ }
+ }
+
+ // Version of the above with seven constructor arguments for the created
+ // object.
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5, typename Arg6, typename Arg7>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+ const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3, const Arg4& arg4,
+ const Arg5& arg5, const Arg6& arg6,
+ const Arg7& arg7) {
+ if (arena == NULL) {
+ return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ } else {
+ return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+ arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ }
+ }
+
+ // Version of the above with eight constructor arguments for the created
+ // object.
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5, typename Arg6, typename Arg7,
+ typename Arg8>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+ const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3, const Arg4& arg4,
+ const Arg5& arg5, const Arg6& arg6,
+ const Arg7& arg7, const Arg8& arg8) {
+ if (arena == NULL) {
+ return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+ } else {
+ return arena->CreateInternal<T>(
+ google::protobuf::internal::has_trivial_destructor<T>::value,
+ arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+ }
+ }
+
+ // Create an array of object type T on the arena *without* invoking the
+ // constructor of T. If `arena` is null, then the return value should be freed
+ // with `delete[] x;` (or `::operator delete[](x);`).
+ // To ensure safe uses, this function checks at compile time
+ // (when compiled as C++11) that T is trivially default-constructible and
+ // trivially destructible.
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
static T* CreateArray(::google::protobuf::Arena* arena, size_t num_elements) {
if (arena == NULL) {
- return new T[num_elements];
+ return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
} else {
- return static_cast<T*>(
- arena->AllocateAligned(num_elements * sizeof(T)));
+ return arena->CreateInternalRawArray<T>(num_elements);
}
}
@@ -211,6 +425,8 @@ class LIBPROTOBUF_EXPORT Arena {
// of the underlying blocks. The total space used may not include the new
// blocks that are allocated by this arena from other threads concurrently
// with the call to this method.
+ uint64 SpaceAllocated() const GOOGLE_ATTRIBUTE_NOINLINE;
+ // As above, but does not include any free space in underlying blocks.
uint64 SpaceUsed() const GOOGLE_ATTRIBUTE_NOINLINE;
// Frees all storage allocated by this arena after calling destructors
@@ -253,7 +469,7 @@ class LIBPROTOBUF_EXPORT Arena {
// latter is a virtual call, while this method is a templated call that
// resolves at compile-time.
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- static inline ::google::protobuf::Arena* GetArena(T* value) {
+ static inline ::google::protobuf::Arena* GetArena(const T* value) {
return GetArenaInternal(value, static_cast<T*>(0));
}
@@ -295,9 +511,6 @@ class LIBPROTOBUF_EXPORT Arena {
// data follows
};
- void* (*block_alloc)(size_t); // Allocates a free block of a particular size.
- void (*block_dealloc)(void*, size_t); // Deallocates the given block.
-
template<typename Type> friend class ::google::protobuf::internal::GenericTypeHandler;
friend class MockArena; // For unit-testing.
friend class internal::ArenaString; // For AllocateAligned.
@@ -313,24 +526,30 @@ class LIBPROTOBUF_EXPORT Arena {
static const size_t kHeaderSize = sizeof(Block);
static google::protobuf::internal::SequenceNumber lifecycle_id_generator_;
#ifdef PROTOBUF_USE_DLLS
+ // Thread local variables cannot be exposed through DLL interface but we can
+ // wrap them in static functions.
+ static ThreadCache& thread_cache();
+#elif defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
+ // Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread
+ // local storage class we implemented.
+ // iOS also does not support the GOOGLE_THREAD_LOCAL keyword.
static ThreadCache& thread_cache();
#else
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
static ThreadCache& thread_cache() { return thread_cache_; }
#endif
- // SFINAE for skipping addition to delete list for a Type. This is mainly to
- // skip proto2/proto1 message objects with cc_enable_arenas=true from being
- // part of the delete list. Also, note, compiler will optimize out the branch
- // in CreateInternal<T>.
- //
+ // SFINAE for skipping addition to delete list for a message type when created
+ // with CreateMessage. This is mainly to skip proto2/proto1 message objects
+ // with cc_enable_arenas=true from being part of the delete list. Also, note,
+ // compiler will optimize out the branch in CreateInternal<T>.
template<typename T>
static inline bool SkipDeleteList(typename T::DestructorSkippable_*) {
return true;
}
- // For non message objects, we skip addition to delete list if the object has
- // a trivial destructor.
+ // For message objects that don't have the DestructorSkippable_ trait, we
+ // always add to the delete list.
template<typename T>
static inline bool SkipDeleteList(...) {
return google::protobuf::internal::has_trivial_destructor<T>::value;
@@ -352,10 +571,18 @@ class LIBPROTOBUF_EXPORT Arena {
return Create<T>(arena);
}
+ // Just allocate the required size for the given type assuming the
+ // type has a trivial constructor.
+ template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ inline T* CreateInternalRawArray(size_t num_elements) {
+ return static_cast<T*>(
+ AllocateAligned(RTTI_TYPE_ID(T), sizeof(T) * num_elements));
+ }
+
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
inline T* CreateInternal(
bool skip_explicit_ownership) {
- T* t = new (AllocateAligned(sizeof(T))) T();
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T();
if (!skip_explicit_ownership) {
AddListNode(t, &internal::arena_destruct_object<T>);
}
@@ -365,7 +592,7 @@ class LIBPROTOBUF_EXPORT Arena {
template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
inline T* CreateInternal(
bool skip_explicit_ownership, const Arg& arg) {
- T* t = new (AllocateAligned(sizeof(T))) T(arg);
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg);
if (!skip_explicit_ownership) {
AddListNode(t, &internal::arena_destruct_object<T>);
}
@@ -375,7 +602,106 @@ class LIBPROTOBUF_EXPORT Arena {
template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
inline T* CreateInternal(
bool skip_explicit_ownership, const Arg1& arg1, const Arg2& arg2) {
- T* t = new (AllocateAligned(sizeof(T))) T(arg1, arg2);
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2);
+ if (!skip_explicit_ownership) {
+ AddListNode(t, &internal::arena_destruct_object<T>);
+ }
+ return t;
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3) {
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+ T(arg1, arg2, arg3);
+ if (!skip_explicit_ownership) {
+ AddListNode(t, &internal::arena_destruct_object<T>);
+ }
+ return t;
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4) {
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+ T(arg1, arg2, arg3, arg4);
+ if (!skip_explicit_ownership) {
+ AddListNode(t, &internal::arena_destruct_object<T>);
+ }
+ return t;
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4,
+ const Arg5& arg5) {
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+ T(arg1, arg2, arg3, arg4, arg5);
+ if (!skip_explicit_ownership) {
+ AddListNode(t, &internal::arena_destruct_object<T>);
+ }
+ return t;
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5, typename Arg6>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4,
+ const Arg5& arg5,
+ const Arg6& arg6) {
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+ T(arg1, arg2, arg3, arg4, arg5, arg6);
+ if (!skip_explicit_ownership) {
+ AddListNode(t, &internal::arena_destruct_object<T>);
+ }
+ return t;
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5, typename Arg6, typename Arg7>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4,
+ const Arg5& arg5,
+ const Arg6& arg6,
+ const Arg7& arg7) {
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+ T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ if (!skip_explicit_ownership) {
+ AddListNode(t, &internal::arena_destruct_object<T>);
+ }
+ return t;
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5, typename Arg6, typename Arg7,
+ typename Arg8>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4,
+ const Arg5& arg5,
+ const Arg6& arg6,
+ const Arg7& arg7,
+ const Arg8& arg8) {
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+ T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
if (!skip_explicit_ownership) {
AddListNode(t, &internal::arena_destruct_object<T>);
}
@@ -388,6 +714,39 @@ class LIBPROTOBUF_EXPORT Arena {
this);
}
+ template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
+ const Arg& arg) {
+ return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
+ this, arg);
+ }
+
+ template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
+ const Arg1& arg1, const Arg2& arg2) {
+ return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
+ this, arg1, arg2);
+ }
+
+ // CreateInArenaStorage is used to implement map field. Without it,
+ // google::protobuf::Map need to call generated message's protected arena constructor,
+ // which needs to declare google::protobuf::Map as friend of generated message.
+ template <typename T>
+ static void CreateInArenaStorage(T* ptr, Arena* arena) {
+ CreateInArenaStorageInternal(ptr, arena, is_arena_constructable<T>::value);
+ }
+ template <typename T>
+ static void CreateInArenaStorageInternal(
+ T* ptr, Arena* arena, google::protobuf::internal::true_type) {
+ new (ptr) T(arena);
+ }
+
+ template <typename T>
+ static void CreateInArenaStorageInternal(
+ T* ptr, Arena* arena, google::protobuf::internal::false_type) {
+ new (ptr) T;
+ }
+
// These implement Own(), which registers an object for deletion (destructor
// call and operator delete()). The second parameter has type 'true_type' if T
// is a subtype of ::google::protobuf::Message and 'false_type' otherwise. Collapsing
@@ -410,20 +769,27 @@ class LIBPROTOBUF_EXPORT Arena {
// InternalArenaConstructable_ tags can be associated with an arena, and such
// objects must implement a GetArenaNoVirtual() method.
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- static inline ::google::protobuf::Arena* GetArenaInternal(T* value,
+ static inline ::google::protobuf::Arena* GetArenaInternal(const T* value,
typename T::InternalArenaConstructable_*) {
return value->GetArenaNoVirtual();
}
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- static inline ::google::protobuf::Arena* GetArenaInternal(T* value, ...) {
+ static inline ::google::protobuf::Arena* GetArenaInternal(const T* value, ...) {
return NULL;
}
+ // Allocate and also optionally call on_arena_allocation callback with the
+ // allocated type info when the hooks are in place in ArenaOptions and
+ // the cookie is not null.
+ void* AllocateAligned(const std::type_info* allocated, size_t n);
- void* AllocateAligned(size_t size);
+ // Allocate an internal allocation, avoiding optional typed monitoring.
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline void* AllocateAligned(size_t n) {
+ return AllocateAligned(NULL, n);
+ }
- void Init(const ArenaOptions& options);
+ void Init();
// Free all blocks and return the total space used which is the sums of sizes
// of the all the allocated blocks.
@@ -444,8 +810,6 @@ class LIBPROTOBUF_EXPORT Arena {
}
int64 lifecycle_id_; // Unique for each arena. Changes on Reset().
- size_t start_block_size_; // Starting block size of the arena.
- size_t max_block_size_; // Max block size of the arena.
google::protobuf::internal::AtomicWord blocks_; // Head of linked list of all allocated blocks
google::protobuf::internal::AtomicWord hint_; // Fast thread-local block access
@@ -470,9 +834,21 @@ class LIBPROTOBUF_EXPORT Arena {
Block* NewBlock(void* me, Block* my_last_block, size_t n,
size_t start_block_size, size_t max_block_size);
static void* AllocFromBlock(Block* b, size_t n);
+ template <typename Key, typename T>
+ friend class Map;
+
+ // The arena may save a cookie it receives from the external on_init hook
+ // and then use it when calling the on_reset and on_destruction hooks.
+ void* hooks_cookie_;
+
+ ArenaOptions options_;
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Arena);
};
+// Defined above for supporting environments without RTTI.
+#undef RTTI_TYPE_ID
+
template<typename T>
const typename Arena::is_arena_constructable<T>::type
Arena::is_arena_constructable<T>::value =
diff --git a/src/google/protobuf/arena_nc_test.py b/src/google/protobuf/arena_nc_test.py
index 41b1b5f8..87a69b2a 100644
--- a/src/google/protobuf/arena_nc_test.py
+++ b/src/google/protobuf/arena_nc_test.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
@@ -32,11 +32,13 @@
"""Negative compilation unit tests for arena API."""
+import unittest
+
from google3.testing.pybase import fake_target_util
-from google.apputils import basetest
+import unittest
-class ArenaNcTest(basetest.TestCase):
+class ArenaNcTest(unittest.TestCase):
def testCompilerErrors(self):
"""Runs a list of tests to verify compiler error messages."""
@@ -56,4 +58,4 @@ class ArenaNcTest(basetest.TestCase):
)
if __name__ == '__main__':
- basetest.main()
+ unittest.main()
diff --git a/src/google/protobuf/arena_test_util.cc b/src/google/protobuf/arena_test_util.cc
new file mode 100644
index 00000000..21f55c6e
--- /dev/null
+++ b/src/google/protobuf/arena_test_util.cc
@@ -0,0 +1,49 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arena_test_util.h>
+
+
+#define EXPECT_EQ GOOGLE_CHECK_EQ
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+NoHeapChecker::~NoHeapChecker() {
+ capture_alloc.Unhook();
+ EXPECT_EQ(0, capture_alloc.alloc_count());
+ EXPECT_EQ(0, capture_alloc.free_count());
+}
+
+} // namespace internal
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/arena_test_util.h b/src/google/protobuf/arena_test_util.h
new file mode 100644
index 00000000..690cc706
--- /dev/null
+++ b/src/google/protobuf/arena_test_util.h
@@ -0,0 +1,60 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
+#define GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
+
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+class NoHeapChecker {
+ public:
+ NoHeapChecker() {
+ capture_alloc.Hook();
+ }
+ ~NoHeapChecker();
+ private:
+ class NewDeleteCapture {
+ public:
+ // TOOD(xiaofeng): Implement this for opensource protobuf.
+ void Hook() {}
+ void Unhook() {}
+ int alloc_count() { return 0; }
+ int free_count() { return 0; }
+ } capture_alloc;
+};
+
+} // namespace internal
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc
index 9d3d3e3e..6c185695 100644
--- a/src/google/protobuf/arena_unittest.cc
+++ b/src/google/protobuf/arena_unittest.cc
@@ -37,18 +37,23 @@
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <string>
+#include <typeinfo>
#include <vector>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arena_test_util.h>
#include <google/protobuf/test_util.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/unittest_arena.pb.h>
#include <google/protobuf/unittest_no_arena.pb.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/message.h>
#include <google/protobuf/message_lite.h>
#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/wire_format_lite.h>
#include <google/protobuf/unknown_field_set.h>
#include <gtest/gtest.h>
@@ -91,6 +96,60 @@ class SimpleDataType {
private:
Notifier* notifier_;
};
+
+// A simple class that does not allow copying and so cannot be used as a
+// parameter type without "const &".
+class PleaseDontCopyMe {
+ public:
+ explicit PleaseDontCopyMe(int value) : value_(value) {}
+
+ int value() const { return value_; }
+
+ private:
+ int value_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PleaseDontCopyMe);
+};
+
+// A class that takes four different types as constructor arguments.
+class MustBeConstructedWithOneThroughFour {
+ public:
+ MustBeConstructedWithOneThroughFour(
+ int one, const char* two, const string& three,
+ const PleaseDontCopyMe* four)
+ : one_(one), two_(two), three_(three), four_(four) {}
+
+ int one_;
+ const char* const two_;
+ string three_;
+ const PleaseDontCopyMe* four_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughFour);
+};
+
+// A class that takes eight different types as constructor arguments.
+class MustBeConstructedWithOneThroughEight {
+ public:
+ MustBeConstructedWithOneThroughEight(
+ int one, const char* two, const string& three,
+ const PleaseDontCopyMe* four, int five, const char* six,
+ const string& seven, const string& eight)
+ : one_(one), two_(two), three_(three), four_(four), five_(five),
+ six_(six), seven_(seven), eight_(eight) {}
+
+ int one_;
+ const char* const two_;
+ string three_;
+ const PleaseDontCopyMe* four_;
+ int five_;
+ const char* const six_;
+ string seven_;
+ string eight_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughEight);
+};
+
} // namespace
TEST(ArenaTest, ArenaConstructable) {
@@ -122,6 +181,40 @@ TEST(ArenaTest, BasicCreate) {
EXPECT_EQ(2, notifier.GetCount());
}
+TEST(ArenaTest, CreateWithFourConstructorArguments) {
+ Arena arena;
+ const string three("3");
+ const PleaseDontCopyMe four(4);
+ const MustBeConstructedWithOneThroughFour* new_object =
+ Arena::Create<MustBeConstructedWithOneThroughFour>(
+ &arena, 1, "2", three, &four);
+ EXPECT_TRUE(new_object != NULL);
+ ASSERT_EQ(1, new_object->one_);
+ ASSERT_STREQ("2", new_object->two_);
+ ASSERT_EQ("3", new_object->three_);
+ ASSERT_EQ(4, new_object->four_->value());
+}
+
+TEST(ArenaTest, CreateWithEightConstructorArguments) {
+ Arena arena;
+ const string three("3");
+ const PleaseDontCopyMe four(4);
+ const string seven("7");
+ const string eight("8");
+ const MustBeConstructedWithOneThroughEight* new_object =
+ Arena::Create<MustBeConstructedWithOneThroughEight>(
+ &arena, 1, "2", three, &four, 5, "6", seven, eight);
+ EXPECT_TRUE(new_object != NULL);
+ ASSERT_EQ(1, new_object->one_);
+ ASSERT_STREQ("2", new_object->two_);
+ ASSERT_EQ("3", new_object->three_);
+ ASSERT_EQ(4, new_object->four_->value());
+ ASSERT_EQ(5, new_object->five_);
+ ASSERT_STREQ("6", new_object->six_);
+ ASSERT_EQ("7", new_object->seven_);
+ ASSERT_EQ("8", new_object->eight_);
+}
+
TEST(ArenaTest, InitialBlockTooSmall) {
// Construct a small (64 byte) initial block of memory to be used by the
// arena allocator; then, allocate an object which will not fit in the
@@ -380,6 +473,7 @@ TEST(ArenaTest, ReleaseFromArenaMessageMakesCopy) {
delete nested_string;
}
+#ifndef GOOGLE_PROTOBUF_NO_RTTI
TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) {
TestAllTypes::NestedMessage* nested_msg = NULL;
// Note: no string: reflection API only supports releasing submessages.
@@ -390,12 +484,13 @@ TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) {
const Reflection* r = arena_message->GetReflection();
const FieldDescriptor* f = arena_message->GetDescriptor()->FindFieldByName(
"optional_nested_message");
- nested_msg = dynamic_cast<TestAllTypes::NestedMessage*>(
+ nested_msg = static_cast<TestAllTypes::NestedMessage*>(
r->ReleaseMessage(arena_message, f));
}
EXPECT_EQ(42, nested_msg->bb());
delete nested_msg;
}
+#endif // !GOOGLE_PROTOBUF_NO_RTTI
TEST(ArenaTest, UnsafeArenaReleaseDoesNotMakeCopy) {
Arena arena;
@@ -671,6 +766,57 @@ TEST(ArenaTest, UnsafeArenaAddAllocated) {
}
}
+TEST(ArenaTest, UnsafeArenaRelease) {
+ Arena arena;
+ TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+
+ string* s = new string("test string");
+ message->unsafe_arena_set_allocated_optional_string(s);
+ EXPECT_TRUE(message->has_optional_string());
+ EXPECT_EQ("test string", message->optional_string());
+ s = message->unsafe_arena_release_optional_string();
+ EXPECT_FALSE(message->has_optional_string());
+ delete s;
+
+ s = new string("test string");
+ message->unsafe_arena_set_allocated_oneof_string(s);
+ EXPECT_TRUE(message->has_oneof_string());
+ EXPECT_EQ("test string", message->oneof_string());
+ s = message->unsafe_arena_release_oneof_string();
+ EXPECT_FALSE(message->has_oneof_string());
+ delete s;
+}
+
+TEST(ArenaTest, ArenaOneofReflection) {
+ Arena arena;
+ TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+ const Descriptor* desc = message->GetDescriptor();
+ const Reflection* refl = message->GetReflection();
+
+ const FieldDescriptor* string_field = desc->FindFieldByName(
+ "oneof_string");
+ const FieldDescriptor* msg_field = desc->FindFieldByName(
+ "oneof_nested_message");
+ const OneofDescriptor* oneof = desc->FindOneofByName(
+ "oneof_field");
+
+ refl->SetString(message, string_field, "Test value");
+ EXPECT_TRUE(refl->HasOneof(*message, oneof));
+ refl->ClearOneof(message, oneof);
+ EXPECT_FALSE(refl->HasOneof(*message, oneof));
+
+ Message* submsg = refl->MutableMessage(message, msg_field);
+ EXPECT_TRUE(refl->HasOneof(*message, oneof));
+ refl->ClearOneof(message, oneof);
+ EXPECT_FALSE(refl->HasOneof(*message, oneof));
+ refl->MutableMessage(message, msg_field);
+ EXPECT_TRUE(refl->HasOneof(*message, oneof));
+ submsg = refl->ReleaseMessage(message, msg_field);
+ EXPECT_FALSE(refl->HasOneof(*message, oneof));
+ EXPECT_TRUE(submsg->GetArena() == NULL);
+ delete submsg;
+}
+
namespace {
void TestSwapRepeatedField(Arena* arena1, Arena* arena2) {
// Test "safe" (copying) semantics for direct Swap() on RepeatedPtrField
@@ -746,27 +892,6 @@ TEST(ArenaTest, ExtensionsOnArena) {
protobuf_unittest::optional_nested_message_extension)->set_bb(42);
}
-class NoHeapChecker {
- public:
- NoHeapChecker() {
- capture_alloc.Hook();
- }
- ~NoHeapChecker() {
- capture_alloc.Unhook();
- EXPECT_EQ(0, capture_alloc.alloc_count());
- EXPECT_EQ(0, capture_alloc.free_count());
- }
- private:
- class NewDeleteCapture {
- public:
- // TOOD(xiaofeng): Implement this for opensource protobuf.
- void Hook() {}
- void Unhook() {}
- int alloc_count() { return 0; }
- int free_count() { return 0; }
- } capture_alloc;
-};
-
TEST(ArenaTest, RepeatedFieldOnArena) {
// Preallocate an initial arena block to avoid mallocs during hooked region.
std::vector<char> arena_block(1024 * 1024);
@@ -776,7 +901,7 @@ TEST(ArenaTest, RepeatedFieldOnArena) {
Arena arena(options);
{
- NoHeapChecker no_heap;
+ internal::NoHeapChecker no_heap;
// Fill some repeated fields on the arena to test for leaks. Also verify no
// memory allocations.
@@ -846,6 +971,7 @@ TEST(ArenaTest, RepeatedFieldOnArena) {
}
+#ifndef GOOGLE_PROTOBUF_NO_RTTI
TEST(ArenaTest, MutableMessageReflection) {
Arena arena;
TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
@@ -853,7 +979,7 @@ TEST(ArenaTest, MutableMessageReflection) {
const Descriptor* d = message->GetDescriptor();
const FieldDescriptor* field = d->FindFieldByName("optional_nested_message");
TestAllTypes::NestedMessage* submessage =
- dynamic_cast<TestAllTypes::NestedMessage*>(
+ static_cast<TestAllTypes::NestedMessage*>(
r->MutableMessage(message, field));
TestAllTypes::NestedMessage* submessage_expected =
message->mutable_optional_nested_message();
@@ -862,13 +988,14 @@ TEST(ArenaTest, MutableMessageReflection) {
EXPECT_EQ(&arena, submessage->GetArena());
const FieldDescriptor* oneof_field = d->FindFieldByName("oneof_nested_message");
- submessage = dynamic_cast<TestAllTypes::NestedMessage*>(
+ submessage = static_cast<TestAllTypes::NestedMessage*>(
r->MutableMessage(message, oneof_field));
submessage_expected = message->mutable_oneof_nested_message();
EXPECT_EQ(submessage_expected, submessage);
EXPECT_EQ(&arena, submessage->GetArena());
}
+#endif // !GOOGLE_PROTOBUF_NO_RTTI
namespace {
@@ -911,7 +1038,7 @@ TEST(ArenaTest, NoHeapAllocationsTest) {
arena.Reset();
}
-
+#ifndef GOOGLE_PROTOBUF_NO_RTTI
// Test construction on an arena via generic MessageLite interface. We should be
// able to successfully deserialize on the arena without incurring heap
// allocations, i.e., everything should still be arena-allocation-aware.
@@ -921,8 +1048,7 @@ TEST(ArenaTest, MessageLiteOnArena) {
options.initial_block = &arena_block[0];
options.initial_block_size = arena_block.size();
Arena arena(options);
- const google::protobuf::MessageLite* prototype = dynamic_cast<
- const google::protobuf::MessageLite*>(&TestAllTypes::default_instance());
+ const google::protobuf::MessageLite* prototype = &TestAllTypes::default_instance();
TestAllTypes initial_message;
FillArenaAwareFields(&initial_message);
@@ -935,13 +1061,13 @@ TEST(ArenaTest, MessageLiteOnArena) {
EXPECT_TRUE(generic_message != NULL);
EXPECT_EQ(&arena, generic_message->GetArena());
EXPECT_TRUE(generic_message->ParseFromString(serialized));
- TestAllTypes* deserialized = dynamic_cast<TestAllTypes*>(generic_message);
- EXPECT_TRUE(deserialized != NULL);
+ TestAllTypes* deserialized = static_cast<TestAllTypes*>(generic_message);
EXPECT_EQ(42, deserialized->optional_int32());
}
arena.Reset();
}
+#endif // !GOOGLE_PROTOBUF_NO_RTTI
// RepeatedField should support non-POD types, and invoke constructors and
@@ -963,16 +1089,23 @@ TEST(ArenaTest, RepeatedFieldWithNonPODType) {
}
}
-TEST(ArenaTest, SpaceUsed) {
+// Align n to next multiple of 8
+namespace {
+uint64 Align8(uint64 n) { return (n + 7) & -8; }
+} // namespace
+
+TEST(ArenaTest, SpaceAllocated_and_Used) {
ArenaOptions options;
options.start_block_size = 256;
options.max_block_size = 8192;
Arena arena_1(options);
+ EXPECT_EQ(0, arena_1.SpaceAllocated());
EXPECT_EQ(0, arena_1.SpaceUsed());
EXPECT_EQ(0, arena_1.Reset());
::google::protobuf::Arena::CreateArray<char>(&arena_1, 320);
// Arena will allocate slightly more than 320 for the block headers.
- EXPECT_LE(320, arena_1.SpaceUsed());
+ EXPECT_LE(320, arena_1.SpaceAllocated());
+ EXPECT_EQ(Align8(320), arena_1.SpaceUsed());
EXPECT_LE(320, arena_1.Reset());
// Test with initial block.
@@ -980,20 +1113,25 @@ TEST(ArenaTest, SpaceUsed) {
options.initial_block = &arena_block[0];
options.initial_block_size = arena_block.size();
Arena arena_2(options);
- EXPECT_EQ(1024, arena_2.SpaceUsed());
+ EXPECT_EQ(1024, arena_2.SpaceAllocated());
+ EXPECT_EQ(0, arena_2.SpaceUsed());
EXPECT_EQ(1024, arena_2.Reset());
::google::protobuf::Arena::CreateArray<char>(&arena_2, 55);
- EXPECT_EQ(1024, arena_2.SpaceUsed());
+ EXPECT_EQ(1024, arena_2.SpaceAllocated());
+ EXPECT_EQ(Align8(55), arena_2.SpaceUsed());
EXPECT_EQ(1024, arena_2.Reset());
// Reset options to test doubling policy explicitly.
options.initial_block = NULL;
options.initial_block_size = 0;
Arena arena_3(options);
+ EXPECT_EQ(0, arena_3.SpaceUsed());
::google::protobuf::Arena::CreateArray<char>(&arena_3, 190);
- EXPECT_EQ(256, arena_3.SpaceUsed());
+ EXPECT_EQ(256, arena_3.SpaceAllocated());
+ EXPECT_EQ(Align8(190), arena_3.SpaceUsed());
::google::protobuf::Arena::CreateArray<char>(&arena_3, 70);
- EXPECT_EQ(256 + 512, arena_3.SpaceUsed());
+ EXPECT_EQ(256 + 512, arena_3.SpaceAllocated());
+ EXPECT_EQ(Align8(190) + Align8(70), arena_3.SpaceUsed());
EXPECT_EQ(256 + 512, arena_3.Reset());
}
@@ -1005,5 +1143,105 @@ TEST(ArenaTest, Alignment) {
}
}
+TEST(ArenaTest, GetArenaShouldReturnTheArenaForArenaAllocatedMessages) {
+ ::google::protobuf::Arena arena;
+ ArenaMessage* message = Arena::CreateMessage<ArenaMessage>(&arena);
+ const ArenaMessage* const_pointer_to_message = message;
+ EXPECT_EQ(&arena, Arena::GetArena(message));
+ EXPECT_EQ(&arena, Arena::GetArena(const_pointer_to_message));
+}
+
+TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaAllocatedMessages) {
+ ArenaMessage message;
+ const ArenaMessage* const_pointer_to_message = &message;
+ EXPECT_EQ(NULL, Arena::GetArena(&message));
+ EXPECT_EQ(NULL, Arena::GetArena(const_pointer_to_message));
+}
+
+TEST(ArenaTest, UnsafeSetAllocatedOnArena) {
+ ::google::protobuf::Arena arena;
+ TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+ EXPECT_FALSE(message->has_optional_string());
+
+ string owned_string = "test with long enough content to heap-allocate";
+ message->unsafe_arena_set_allocated_optional_string(&owned_string);
+ EXPECT_TRUE(message->has_optional_string());
+
+ message->unsafe_arena_set_allocated_optional_string(NULL);
+ EXPECT_FALSE(message->has_optional_string());
+}
+
+// A helper utility class to only contain static hook functions, some
+// counters to be used to verify the counters have been called and a cookie
+// value to be verified.
+class ArenaHooksTestUtil {
+ public:
+ static void* on_init(::google::protobuf::Arena* arena) {
+ ++num_init;
+ int* cookie = new int(kCookieValue);
+ return static_cast<void*>(cookie);
+ }
+
+ static void on_allocation(const std::type_info* /*unused*/, uint64 alloc_size,
+ void* cookie) {
+ ++num_allocations;
+ int cookie_value = *static_cast<int*>(cookie);
+ EXPECT_EQ(kCookieValue, cookie_value);
+ }
+
+ static void on_reset(::google::protobuf::Arena* arena, void* cookie,
+ uint64 space_used) {
+ ++num_reset;
+ int cookie_value = *static_cast<int*>(cookie);
+ EXPECT_EQ(kCookieValue, cookie_value);
+ }
+
+ static void on_destruction(::google::protobuf::Arena* arena, void* cookie,
+ uint64 space_used) {
+ ++num_destruct;
+ int cookie_value = *static_cast<int*>(cookie);
+ EXPECT_EQ(kCookieValue, cookie_value);
+ delete static_cast<int*>(cookie);
+ }
+
+ static const int kCookieValue = 999;
+ static uint32 num_init;
+ static uint32 num_allocations;
+ static uint32 num_reset;
+ static uint32 num_destruct;
+};
+uint32 ArenaHooksTestUtil::num_init = 0;
+uint32 ArenaHooksTestUtil::num_allocations = 0;
+uint32 ArenaHooksTestUtil::num_reset = 0;
+uint32 ArenaHooksTestUtil::num_destruct = 0;
+const int ArenaHooksTestUtil::kCookieValue;
+
+// Test the hooks are correctly called and that the cookie is passed.
+TEST(ArenaTest, ArenaHooksSanity) {
+ ::google::protobuf::ArenaOptions options;
+ options.on_arena_init = ArenaHooksTestUtil::on_init;
+ options.on_arena_allocation = ArenaHooksTestUtil::on_allocation;
+ options.on_arena_reset = ArenaHooksTestUtil::on_reset;
+ options.on_arena_destruction = ArenaHooksTestUtil::on_destruction;
+
+ // Scope for defining the arena
+ {
+ ::google::protobuf::Arena arena(options);
+ EXPECT_EQ(1, ArenaHooksTestUtil::num_init);
+ EXPECT_EQ(0, ArenaHooksTestUtil::num_allocations);
+ ::google::protobuf::Arena::Create<uint64>(&arena);
+ if (::google::protobuf::internal::has_trivial_destructor<uint64>::value) {
+ EXPECT_EQ(1, ArenaHooksTestUtil::num_allocations);
+ } else {
+ EXPECT_EQ(2, ArenaHooksTestUtil::num_allocations);
+ }
+ arena.Reset();
+ arena.Reset();
+ EXPECT_EQ(2, ArenaHooksTestUtil::num_reset);
+ }
+ EXPECT_EQ(3, ArenaHooksTestUtil::num_reset);
+ EXPECT_EQ(1, ArenaHooksTestUtil::num_destruct);
+}
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h
index 321a8ccd..b989f151 100644
--- a/src/google/protobuf/compiler/code_generator.h
+++ b/src/google/protobuf/compiler/code_generator.h
@@ -79,6 +79,37 @@ class LIBPROTOC_EXPORT CodeGenerator {
GeneratorContext* generator_context,
string* error) const = 0;
+ // Generates code for all given proto files, generating one or more files in
+ // the given output directory.
+ //
+ // This method should be called instead of |Generate()| when
+ // |HasGenerateAll()| returns |true|. It is used to emulate legacy semantics
+ // when more than one `.proto` file is specified on one compiler invocation.
+ //
+ // WARNING: Please do not use unless legacy semantics force the code generator
+ // to produce a single output file for all input files, or otherwise require
+ // an examination of all input files first. The canonical code generator
+ // design produces one output file per input .proto file, and we do not wish
+ // to encourage alternate designs.
+ //
+ // A parameter is given as passed on the command line, as in |Generate()|
+ // above.
+ //
+ // Returns true if successful. Otherwise, sets *error to a description of
+ // the problem (e.g. "invalid parameter") and returns false.
+ virtual bool GenerateAll(const vector<const FileDescriptor*>& files,
+ const string& parameter,
+ GeneratorContext* generator_context,
+ string* error) const {
+ *error = "Unimplemented GenerateAll() method.";
+ return false;
+ }
+
+ // Returns true if the code generator expects to receive all FileDescriptors
+ // at once (via |GenerateAll()|), rather than one at a time (via
+ // |Generate()|). This is required to implement legacy semantics.
+ virtual bool HasGenerateAll() const { return false; }
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodeGenerator);
};
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 13250702..e8871861 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -48,12 +48,15 @@
#include <iostream>
#include <ctype.h>
-#include <google/protobuf/stubs/hash.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#ifdef __APPLE__
+#include <mach-o/dyld.h>
+#endif
+
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/compiler/importer.h>
@@ -152,7 +155,7 @@ bool VerifyDirectoryExists(const string& path) {
if (path.empty()) return true;
if (access(path.c_str(), F_OK) == -1) {
- cerr << path << ": " << strerror(errno) << endl;
+ std::cerr << path << ": " << strerror(errno) << std::endl;
return false;
} else {
return true;
@@ -171,8 +174,8 @@ bool TryCreateParentDirectory(const string& prefix, const string& filename) {
path_so_far += parts[i];
if (mkdir(path_so_far.c_str(), 0777) != 0) {
if (errno != EEXIST) {
- cerr << filename << ": while trying to create directory "
- << path_so_far << ": " << strerror(errno) << endl;
+ std::cerr << filename << ": while trying to create directory "
+ << path_so_far << ": " << strerror(errno) << std::endl;
return false;
}
}
@@ -182,6 +185,78 @@ bool TryCreateParentDirectory(const string& prefix, const string& filename) {
return true;
}
+// Get the absolute path of this protoc binary.
+bool GetProtocAbsolutePath(string* path) {
+#ifdef _WIN32
+ char buffer[MAX_PATH];
+ int len = GetModuleFileNameA(NULL, buffer, MAX_PATH);
+#elif __APPLE__
+ char buffer[PATH_MAX];
+ int len = 0;
+
+ char dirtybuffer[PATH_MAX];
+ uint32_t size = sizeof(dirtybuffer);
+ if (_NSGetExecutablePath(dirtybuffer, &size) == 0) {
+ realpath(dirtybuffer, buffer);
+ len = strlen(buffer);
+ }
+#else
+ char buffer[PATH_MAX];
+ int len = readlink("/proc/self/exe", buffer, PATH_MAX);
+#endif
+ if (len > 0) {
+ path->assign(buffer, len);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+// Whether a path is where google/protobuf/descriptor.proto and other well-known
+// type protos are installed.
+bool IsInstalledProtoPath(const string& path) {
+ // Checking the descriptor.proto file should be good enough.
+ string file_path = path + "/google/protobuf/descriptor.proto";
+ return access(file_path.c_str(), F_OK) != -1;
+}
+
+// Add the paths where google/protobuf/descritor.proto and other well-known
+// type protos are installed.
+void AddDefaultProtoPaths(vector<pair<string, string> >* paths) {
+ // TODO(xiaofeng): The code currently only checks relative paths of where
+ // the protoc binary is installed. We probably should make it handle more
+ // cases than that.
+ string path;
+ if (!GetProtocAbsolutePath(&path)) {
+ return;
+ }
+ // Strip the binary name.
+ size_t pos = path.find_last_of("/\\");
+ if (pos == string::npos || pos == 0) {
+ return;
+ }
+ path = path.substr(0, pos);
+ // Check the binary's directory.
+ if (IsInstalledProtoPath(path)) {
+ paths->push_back(pair<string, string>("", path));
+ return;
+ }
+ // Check if there is an include subdirectory.
+ if (IsInstalledProtoPath(path + "/include")) {
+ paths->push_back(pair<string, string>("", path + "/include"));
+ return;
+ }
+ // Check if the upper level directory has an "include" subdirectory.
+ pos = path.find_last_of("/\\");
+ if (pos == string::npos || pos == 0) {
+ return;
+ }
+ path = path.substr(0, pos);
+ if (IsInstalledProtoPath(path + "/include")) {
+ paths->push_back(pair<string, string>("", path + "/include"));
+ return;
+ }
+}
} // namespace
// A MultiFileErrorCollector that prints errors to stderr.
@@ -201,9 +276,9 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS &&
tree_ != NULL &&
tree_->VirtualFileToDiskFile(filename, &dfile)) {
- cerr << dfile;
+ std::cerr << dfile;
} else {
- cerr << filename;
+ std::cerr << filename;
}
// Users typically expect 1-based line/column numbers, so we add 1
@@ -212,15 +287,16 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
// Allow for both GCC- and Visual-Studio-compatible output.
switch (format_) {
case CommandLineInterface::ERROR_FORMAT_GCC:
- cerr << ":" << (line + 1) << ":" << (column + 1);
+ std::cerr << ":" << (line + 1) << ":" << (column + 1);
break;
case CommandLineInterface::ERROR_FORMAT_MSVS:
- cerr << "(" << (line + 1) << ") : error in column=" << (column + 1);
+ std::cerr << "(" << (line + 1)
+ << ") : error in column=" << (column + 1);
break;
}
}
- cerr << ": " << message << endl;
+ std::cerr << ": " << message << std::endl;
}
// implements io::ErrorCollector -----------------------------------
@@ -254,6 +330,9 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext {
// format, unless one has already been written.
void AddJarManifest();
+ // Get name of all output files.
+ void GetOutputFilenames(vector<string>* output_filenames);
+
// implements GeneratorContext --------------------------------------
io::ZeroCopyOutputStream* Open(const string& filename);
io::ZeroCopyOutputStream* OpenForAppend(const string& filename);
@@ -345,7 +424,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk(
if (file_descriptor < 0) {
int error = errno;
- cerr << filename << ": " << strerror(error);
+ std::cerr << filename << ": " << strerror(error);
return false;
}
@@ -369,9 +448,9 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk(
if (write_result < 0) {
int error = errno;
- cerr << filename << ": write: " << strerror(error);
+ std::cerr << filename << ": write: " << strerror(error);
} else {
- cerr << filename << ": write() returned zero?" << endl;
+ std::cerr << filename << ": write() returned zero?" << std::endl;
}
return false;
}
@@ -382,7 +461,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk(
if (close(file_descriptor) != 0) {
int error = errno;
- cerr << filename << ": close: " << strerror(error);
+ std::cerr << filename << ": close: " << strerror(error);
return false;
}
}
@@ -405,7 +484,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip(
if (file_descriptor < 0) {
int error = errno;
- cerr << filename << ": " << strerror(error);
+ std::cerr << filename << ": " << strerror(error);
return false;
}
@@ -421,11 +500,11 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip(
zip_writer.WriteDirectory();
if (stream.GetErrno() != 0) {
- cerr << filename << ": " << strerror(stream.GetErrno()) << endl;
+ std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl;
}
if (!stream.Close()) {
- cerr << filename << ": " << strerror(stream.GetErrno()) << endl;
+ std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl;
}
return true;
@@ -441,6 +520,14 @@ void CommandLineInterface::GeneratorContextImpl::AddJarManifest() {
}
}
+void CommandLineInterface::GeneratorContextImpl::GetOutputFilenames(
+ vector<string>* output_filenames) {
+ for (map<string, string*>::iterator iter = files_.begin();
+ iter != files_.end(); ++iter) {
+ output_filenames->push_back(iter->first);
+ }
+}
+
io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open(
const string& filename) {
return new MemoryOutputStream(this, filename, false);
@@ -490,7 +577,8 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() {
if (append_mode_) {
(*map_slot)->append(data_);
} else {
- cerr << filename_ << ": Tried to write the same file twice." << endl;
+ std::cerr << filename_ << ": Tried to write the same file twice."
+ << std::endl;
directory_->had_error_ = true;
}
return;
@@ -508,8 +596,9 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() {
// Find the file we are going to insert into.
if (*map_slot == NULL) {
- cerr << filename_ << ": Tried to insert into file that doesn't exist."
- << endl;
+ std::cerr << filename_
+ << ": Tried to insert into file that doesn't exist."
+ << std::endl;
directory_->had_error_ = true;
return;
}
@@ -521,8 +610,8 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() {
string::size_type pos = target->find(magic_string);
if (pos == string::npos) {
- cerr << filename_ << ": insertion point \"" << insertion_point_
- << "\" not found." << endl;
+ std::cerr << filename_ << ": insertion point \"" << insertion_point_
+ << "\" not found." << std::endl;
directory_->had_error_ = true;
return;
}
@@ -631,6 +720,8 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
break;
}
+ AddDefaultProtoPaths(&proto_path_);
+
// Set up the source tree.
DiskSourceTree source_tree;
for (int i = 0; i < proto_path_.size(); i++) {
@@ -670,7 +761,6 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
// We construct a separate GeneratorContext for each output location. Note
// that two code generators may output to the same location, in which case
// they should share a single GeneratorContext so that OpenForInsert() works.
- typedef hash_map<string, GeneratorContextImpl*> GeneratorContextMap;
GeneratorContextMap output_directories;
// Generate output.
@@ -717,6 +807,13 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
}
}
+ if (!dependency_out_name_.empty()) {
+ if (!GenerateDependencyManifestFile(parsed_files, output_directories,
+ &source_tree)) {
+ return 1;
+ }
+ }
+
STLDeleteValues(&output_directories);
if (!descriptor_set_name_.empty()) {
@@ -775,6 +872,7 @@ void CommandLineInterface::Clear() {
output_directives_.clear();
codec_type_.clear();
descriptor_set_name_.clear();
+ dependency_out_name_.clear();
mode_ = MODE_COMPILE;
print_mode_ = PRINT_NONE;
@@ -793,27 +891,31 @@ bool CommandLineInterface::MakeInputsBeProtoPathRelative(
input_files_[i] = virtual_file;
break;
case DiskSourceTree::SHADOWED:
- cerr << input_files_[i] << ": Input is shadowed in the --proto_path "
- "by \"" << shadowing_disk_file << "\". Either use the latter "
- "file as your input or reorder the --proto_path so that the "
- "former file's location comes first." << endl;
+ std::cerr << input_files_[i]
+ << ": Input is shadowed in the --proto_path by \""
+ << shadowing_disk_file
+ << "\". Either use the latter file as your input or reorder "
+ "the --proto_path so that the former file's location "
+ "comes first." << std::endl;
return false;
case DiskSourceTree::CANNOT_OPEN:
- cerr << input_files_[i] << ": " << strerror(errno) << endl;
+ std::cerr << input_files_[i] << ": " << strerror(errno) << std::endl;
return false;
case DiskSourceTree::NO_MAPPING:
// First check if the file exists at all.
if (access(input_files_[i].c_str(), F_OK) < 0) {
// File does not even exist.
- cerr << input_files_[i] << ": " << strerror(ENOENT) << endl;
+ std::cerr << input_files_[i] << ": " << strerror(ENOENT) << std::endl;
} else {
- cerr << input_files_[i] << ": File does not reside within any path "
- "specified using --proto_path (or -I). You must specify a "
- "--proto_path which encompasses this file. Note that the "
- "proto_path must be an exact prefix of the .proto file "
- "names -- protoc is too dumb to figure out when two paths "
- "(e.g. absolute and relative) are equivalent (it's harder "
- "than you think)." << endl;
+ std::cerr
+ << input_files_[i]
+ << ": File does not reside within any path "
+ "specified using --proto_path (or -I). You must specify a "
+ "--proto_path which encompasses this file. Note that the "
+ "proto_path must be an exact prefix of the .proto file "
+ "names -- protoc is too dumb to figure out when two paths "
+ "(e.g. absolute and relative) are equivalent (it's harder "
+ "than you think)." << std::endl;
}
return false;
}
@@ -833,9 +935,10 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
if (ParseArgument(argv[i], &name, &value)) {
// Returned true => Use the next argument as the flag value.
if (i + 1 == argc || argv[i+1][0] == '-') {
- cerr << "Missing value for flag: " << name << endl;
+ std::cerr << "Missing value for flag: " << name << std::endl;
if (name == "--decode") {
- cerr << "To decode an unknown message, use --decode_raw." << endl;
+ std::cerr << "To decode an unknown message, use --decode_raw."
+ << std::endl;
}
return PARSE_ARGUMENT_FAIL;
} else {
@@ -860,24 +963,36 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
// Check some errror cases.
bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty();
if (decoding_raw && !input_files_.empty()) {
- cerr << "When using --decode_raw, no input files should be given." << endl;
+ std::cerr << "When using --decode_raw, no input files should be given."
+ << std::endl;
return PARSE_ARGUMENT_FAIL;
} else if (!decoding_raw && input_files_.empty()) {
- cerr << "Missing input file." << endl;
+ std::cerr << "Missing input file." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
if (mode_ == MODE_COMPILE && output_directives_.empty() &&
descriptor_set_name_.empty()) {
- cerr << "Missing output directives." << endl;
+ std::cerr << "Missing output directives." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (mode_ != MODE_COMPILE && !dependency_out_name_.empty()) {
+ std::cerr << "Can only use --dependency_out=FILE when generating code."
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (!dependency_out_name_.empty() && input_files_.size() > 1) {
+ std::cerr
+ << "Can only process one input file when using --dependency_out=FILE."
+ << std::endl;
return PARSE_ARGUMENT_FAIL;
}
if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) {
- cerr << "--include_imports only makes sense when combined with "
- "--descriptor_set_out." << endl;
+ std::cerr << "--include_imports only makes sense when combined with "
+ "--descriptor_set_out." << std::endl;
}
if (source_info_in_descriptor_set_ && descriptor_set_name_.empty()) {
- cerr << "--include_source_info only makes sense when combined with "
- "--descriptor_set_out." << endl;
+ std::cerr << "--include_source_info only makes sense when combined with "
+ "--descriptor_set_out." << std::endl;
}
return PARSE_ARGUMENT_DONE_AND_CONTINUE;
@@ -950,10 +1065,12 @@ CommandLineInterface::InterpretArgument(const string& name,
if (name.empty()) {
// Not a flag. Just a filename.
if (value.empty()) {
- cerr << "You seem to have passed an empty string as one of the "
- "arguments to " << executable_name_ << ". This is actually "
- "sort of hard to do. Congrats. Unfortunately it is not valid "
- "input so the program is going to die now." << endl;
+ std::cerr
+ << "You seem to have passed an empty string as one of the "
+ "arguments to " << executable_name_
+ << ". This is actually "
+ "sort of hard to do. Congrats. Unfortunately it is not valid "
+ "input so the program is going to die now." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
@@ -980,14 +1097,16 @@ CommandLineInterface::InterpretArgument(const string& name,
}
if (disk_path.empty()) {
- cerr << "--proto_path passed empty directory name. (Use \".\" for "
- "current directory.)" << endl;
+ std::cerr
+ << "--proto_path passed empty directory name. (Use \".\" for "
+ "current directory.)" << std::endl;
return PARSE_ARGUMENT_FAIL;
}
// Make sure disk path exists, warn otherwise.
if (access(disk_path.c_str(), F_OK) < 0) {
- cerr << disk_path << ": warning: directory does not exist." << endl;
+ std::cerr << disk_path << ": warning: directory does not exist."
+ << std::endl;
}
// Don't use make_pair as the old/default standard library on Solaris
@@ -998,30 +1117,42 @@ CommandLineInterface::InterpretArgument(const string& name,
} else if (name == "-o" || name == "--descriptor_set_out") {
if (!descriptor_set_name_.empty()) {
- cerr << name << " may only be passed once." << endl;
+ std::cerr << name << " may only be passed once." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
if (value.empty()) {
- cerr << name << " requires a non-empty value." << endl;
+ std::cerr << name << " requires a non-empty value." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
if (mode_ != MODE_COMPILE) {
- cerr << "Cannot use --encode or --decode and generate descriptors at the "
- "same time." << endl;
+ std::cerr
+ << "Cannot use --encode or --decode and generate descriptors at the "
+ "same time." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
descriptor_set_name_ = value;
+ } else if (name == "--dependency_out") {
+ if (!dependency_out_name_.empty()) {
+ std::cerr << name << " may only be passed once." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (value.empty()) {
+ std::cerr << name << " requires a non-empty value." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ dependency_out_name_ = value;
+
} else if (name == "--include_imports") {
if (imports_in_descriptor_set_) {
- cerr << name << " may only be passed once." << endl;
+ std::cerr << name << " may only be passed once." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
imports_in_descriptor_set_ = true;
} else if (name == "--include_source_info") {
if (source_info_in_descriptor_set_) {
- cerr << name << " may only be passed once." << endl;
+ std::cerr << name << " may only be passed once." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
source_info_in_descriptor_set_ = true;
@@ -1032,7 +1163,7 @@ CommandLineInterface::InterpretArgument(const string& name,
} else if (name == "--version") {
if (!version_info_.empty()) {
- cout << version_info_ << endl;
+ std::cout << version_info_ << std::endl;
}
cout << "libprotoc "
<< protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION)
@@ -1045,25 +1176,28 @@ CommandLineInterface::InterpretArgument(const string& name,
} else if (name == "--encode" || name == "--decode" ||
name == "--decode_raw") {
if (mode_ != MODE_COMPILE) {
- cerr << "Only one of --encode and --decode can be specified." << endl;
+ std::cerr << "Only one of --encode and --decode can be specified."
+ << std::endl;
return PARSE_ARGUMENT_FAIL;
}
if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
- cerr << "Cannot use " << name
- << " and generate code or descriptors at the same time." << endl;
+ std::cerr << "Cannot use " << name
+ << " and generate code or descriptors at the same time."
+ << std::endl;
return PARSE_ARGUMENT_FAIL;
}
mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE;
if (value.empty() && name != "--decode_raw") {
- cerr << "Type name for " << name << " cannot be blank." << endl;
+ std::cerr << "Type name for " << name << " cannot be blank." << std::endl;
if (name == "--decode") {
- cerr << "To decode an unknown message, use --decode_raw." << endl;
+ std::cerr << "To decode an unknown message, use --decode_raw."
+ << std::endl;
}
return PARSE_ARGUMENT_FAIL;
} else if (!value.empty() && name == "--decode_raw") {
- cerr << "--decode_raw does not take a parameter." << endl;
+ std::cerr << "--decode_raw does not take a parameter." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
@@ -1075,13 +1209,13 @@ CommandLineInterface::InterpretArgument(const string& name,
} else if (value == "msvs") {
error_format_ = ERROR_FORMAT_MSVS;
} else {
- cerr << "Unknown error format: " << value << endl;
+ std::cerr << "Unknown error format: " << value << std::endl;
return PARSE_ARGUMENT_FAIL;
}
} else if (name == "--plugin") {
if (plugin_prefix_.empty()) {
- cerr << "This compiler does not support plugins." << endl;
+ std::cerr << "This compiler does not support plugins." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
@@ -1107,13 +1241,15 @@ CommandLineInterface::InterpretArgument(const string& name,
} else if (name == "--print_free_field_numbers") {
if (mode_ != MODE_COMPILE) {
- cerr << "Cannot use " << name << " and use --encode, --decode or print "
- << "other info at the same time." << endl;
+ std::cerr << "Cannot use " << name
+ << " and use --encode, --decode or print "
+ << "other info at the same time." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
- cerr << "Cannot use " << name
- << " and generate code or descriptors at the same time." << endl;
+ std::cerr << "Cannot use " << name
+ << " and generate code or descriptors at the same time."
+ << std::endl;
return PARSE_ARGUMENT_FAIL;
}
mode_ = MODE_PRINT;
@@ -1127,7 +1263,7 @@ CommandLineInterface::InterpretArgument(const string& name,
// Check if it's a generator option flag.
generator_info = FindOrNull(generators_by_option_name_, name);
if (generator_info == NULL) {
- cerr << "Unknown flag: " << name << endl;
+ std::cerr << "Unknown flag: " << name << std::endl;
return PARSE_ARGUMENT_FAIL;
} else {
string* parameters = &generator_parameters_[generator_info->flag_name];
@@ -1139,8 +1275,8 @@ CommandLineInterface::InterpretArgument(const string& name,
} else {
// It's an output flag. Add it to the output directives.
if (mode_ != MODE_COMPILE) {
- cerr << "Cannot use --encode, --decode or print .proto info and "
- "generate code at the same time." << endl;
+ std::cerr << "Cannot use --encode, --decode or print .proto info and "
+ "generate code at the same time." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
@@ -1172,7 +1308,7 @@ CommandLineInterface::InterpretArgument(const string& name,
void CommandLineInterface::PrintHelpText() {
// Sorry for indentation here; line wrapping would be uglier.
- cerr <<
+ std::cerr <<
"Usage: " << executable_name_ << " [OPTION] PROTO_FILES\n"
"Parse PROTO_FILES and generate output based on the options given:\n"
" -IPATH, --proto_path=PATH Specify the directory in which to search for\n"
@@ -1206,6 +1342,9 @@ void CommandLineInterface::PrintHelpText() {
" include information about the original\n"
" location of each decl in the source file as\n"
" well as surrounding comments.\n"
+" --dependency_out=FILE Write a dependency output file in the format\n"
+" expected by make. This writes the transitive\n"
+" set of input file paths to FILE\n"
" --error_format=FORMAT Set the format in which to print errors.\n"
" FORMAT may be 'gcc' (the default) or 'msvs'\n"
" (Microsoft Visual Studio format).\n"
@@ -1213,9 +1352,10 @@ void CommandLineInterface::PrintHelpText() {
" defined in the given proto files. Groups share\n"
" the same field number space with the parent \n"
" message. Extension ranges are counted as \n"
-" occupied fields numbers." << endl;
+" occupied fields numbers."
+ << std::endl;
if (!plugin_prefix_.empty()) {
- cerr <<
+ std::cerr <<
" --plugin=EXECUTABLE Specifies a plugin executable to use.\n"
" Normally, protoc searches the PATH for\n"
" plugins, but you may specify additional\n"
@@ -1223,7 +1363,7 @@ void CommandLineInterface::PrintHelpText() {
" Additionally, EXECUTABLE may be of the form\n"
" NAME=PATH, in which case the given plugin name\n"
" is mapped to the given executable even if\n"
-" the executable's own name differs." << endl;
+" the executable's own name differs." << std::endl;
}
for (GeneratorMap::iterator iter = generators_by_flag_name_.begin();
@@ -1231,9 +1371,9 @@ void CommandLineInterface::PrintHelpText() {
// FIXME(kenton): If the text is long enough it will wrap, which is ugly,
// but fixing this nicely (e.g. splitting on spaces) is probably more
// trouble than it's worth.
- cerr << " " << iter->first << "=OUT_DIR "
- << string(19 - iter->first.size(), ' ') // Spaces for alignment.
- << iter->second.help_text << endl;
+ std::cerr << " " << iter->first << "=OUT_DIR "
+ << string(19 - iter->first.size(), ' ') // Spaces for alignment.
+ << iter->second.help_text << std::endl;
}
}
@@ -1256,7 +1396,7 @@ bool CommandLineInterface::GenerateOutput(
if (!GeneratePluginOutput(parsed_files, plugin_name,
output_directive.parameter,
generator_context, &error)) {
- cerr << output_directive.name << ": " << error << endl;
+ std::cerr << output_directive.name << ": " << error << std::endl;
return false;
}
} else {
@@ -1268,14 +1408,95 @@ bool CommandLineInterface::GenerateOutput(
}
parameters.append(generator_parameters_[output_directive.name]);
}
- for (int i = 0; i < parsed_files.size(); i++) {
- if (!output_directive.generator->Generate(parsed_files[i], parameters,
- generator_context, &error)) {
- // Generator returned an error.
- cerr << output_directive.name << ": " << parsed_files[i]->name() << ": "
- << error << endl;
- return false;
+ if (output_directive.generator->HasGenerateAll()) {
+ if (!output_directive.generator->GenerateAll(
+ parsed_files, parameters, generator_context, &error)) {
+ // Generator returned an error.
+ std::cerr << output_directive.name << ": "
+ << ": " << error << std::endl;
+ return false;
+ }
+ } else {
+ for (int i = 0; i < parsed_files.size(); i++) {
+ if (!output_directive.generator->Generate(parsed_files[i], parameters,
+ generator_context, &error)) {
+ // Generator returned an error.
+ std::cerr << output_directive.name << ": " << parsed_files[i]->name()
+ << ": " << error << std::endl;
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool CommandLineInterface::GenerateDependencyManifestFile(
+ const vector<const FileDescriptor*>& parsed_files,
+ const GeneratorContextMap& output_directories,
+ DiskSourceTree* source_tree) {
+ FileDescriptorSet file_set;
+
+ set<const FileDescriptor*> already_seen;
+ for (int i = 0; i < parsed_files.size(); i++) {
+ GetTransitiveDependencies(parsed_files[i],
+ false,
+ &already_seen,
+ file_set.mutable_file());
+ }
+
+ vector<string> output_filenames;
+ for (GeneratorContextMap::const_iterator iter = output_directories.begin();
+ iter != output_directories.end(); ++iter) {
+ const string& location = iter->first;
+ GeneratorContextImpl* directory = iter->second;
+ vector<string> relative_output_filenames;
+ directory->GetOutputFilenames(&relative_output_filenames);
+ for (int i = 0; i < relative_output_filenames.size(); i++) {
+ string output_filename = location + relative_output_filenames[i];
+ if (output_filename.compare(0, 2, "./") == 0) {
+ output_filename = output_filename.substr(2);
}
+ output_filenames.push_back(output_filename);
+ }
+ }
+
+ int fd;
+ do {
+ fd = open(dependency_out_name_.c_str(),
+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ } while (fd < 0 && errno == EINTR);
+
+ if (fd < 0) {
+ perror(dependency_out_name_.c_str());
+ return false;
+ }
+
+ io::FileOutputStream out(fd);
+ io::Printer printer(&out, '$');
+
+ for (int i = 0; i < output_filenames.size(); i++) {
+ printer.Print(output_filenames[i].c_str());
+ if (i == output_filenames.size() - 1) {
+ printer.Print(":");
+ } else {
+ printer.Print(" \\\n");
+ }
+ }
+
+ for (int i = 0; i < file_set.file_size(); i++) {
+ const FileDescriptorProto& file = file_set.file(i);
+ const string& virtual_file = file.name();
+ string disk_file;
+ if (source_tree &&
+ source_tree->VirtualFileToDiskFile(virtual_file, &disk_file)) {
+ printer.Print(" $disk_file$", "disk_file", disk_file);
+ if (i < file_set.file_size() - 1) printer.Print("\\\n");
+ } else {
+ std::cerr << "Unable to identify path for file " << virtual_file
+ << std::endl;
+ return false;
}
}
@@ -1365,7 +1586,7 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) {
// Look up the type.
const Descriptor* type = pool->FindMessageTypeByName(codec_type_);
if (type == NULL) {
- cerr << "Type not defined: " << codec_type_ << endl;
+ std::cerr << "Type not defined: " << codec_type_ << std::endl;
return false;
}
@@ -1391,32 +1612,32 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) {
parser.AllowPartialMessage(true);
if (!parser.Parse(&in, message.get())) {
- cerr << "Failed to parse input." << endl;
+ std::cerr << "Failed to parse input." << std::endl;
return false;
}
} else {
// Input is binary.
if (!message->ParsePartialFromZeroCopyStream(&in)) {
- cerr << "Failed to parse input." << endl;
+ std::cerr << "Failed to parse input." << std::endl;
return false;
}
}
if (!message->IsInitialized()) {
- cerr << "warning: Input message is missing required fields: "
- << message->InitializationErrorString() << endl;
+ std::cerr << "warning: Input message is missing required fields: "
+ << message->InitializationErrorString() << std::endl;
}
if (mode_ == MODE_ENCODE) {
// Output is binary.
if (!message->SerializePartialToZeroCopyStream(&out)) {
- cerr << "output: I/O error." << endl;
+ std::cerr << "output: I/O error." << std::endl;
return false;
}
} else {
// Output is text.
if (!TextFormat::Print(*message, &out)) {
- cerr << "output: I/O error." << endl;
+ std::cerr << "output: I/O error." << std::endl;
return false;
}
}
@@ -1458,12 +1679,14 @@ bool CommandLineInterface::WriteDescriptorSet(
io::FileOutputStream out(fd);
if (!file_set.SerializeToZeroCopyStream(&out)) {
- cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) << endl;
+ std::cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno())
+ << std::endl;
out.Close();
return false;
}
if (!out.Close()) {
- cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) << endl;
+ std::cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno())
+ << std::endl;
return false;
}
@@ -1542,6 +1765,10 @@ void GatherOccupiedFieldRanges(const Descriptor* descriptor,
ranges->insert(FieldRange(descriptor->extension_range(i)->start,
descriptor->extension_range(i)->end));
}
+ for (int i = 0; i < descriptor->reserved_range_count(); ++i) {
+ ranges->insert(FieldRange(descriptor->reserved_range(i)->start,
+ descriptor->reserved_range(i)->end));
+ }
// Handle the nested messages/groups in declaration order to make it
// post-order strict.
for (int i = 0; i < descriptor->nested_type_count(); ++i) {
@@ -1582,7 +1809,7 @@ void FormatFreeFieldNumbers(const string& name,
if (next_free_number <= FieldDescriptor::kMaxNumber) {
StringAppendF(&output, " %d-INF", next_free_number);
}
- cout << output << endl;
+ std::cout << output << std::endl;
}
} // namespace
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index 74a0adb4..7e611c44 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -39,6 +39,7 @@
#define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/hash.h>
#include <string>
#include <vector>
#include <map>
@@ -190,6 +191,7 @@ class LIBPROTOC_EXPORT CommandLineInterface {
class ErrorPrinter;
class GeneratorContextImpl;
class MemoryOutputStream;
+ typedef hash_map<string, GeneratorContextImpl*> GeneratorContextMap;
// Clear state from previous Run().
void Clear();
@@ -247,6 +249,12 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// Implements the --descriptor_set_out option.
bool WriteDescriptorSet(const vector<const FileDescriptor*> parsed_files);
+ // Implements the --dependency_out option
+ bool GenerateDependencyManifestFile(
+ const vector<const FileDescriptor*>& parsed_files,
+ const GeneratorContextMap& output_directories,
+ DiskSourceTree* source_tree);
+
// Get all transitive dependencies of the given file (including the file
// itself), adding them to the given list of FileDescriptorProtos. The
// protos will be ordered such that every file is listed before any file that
@@ -353,6 +361,10 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// FileDescriptorSet should be written. Otherwise, empty.
string descriptor_set_name_;
+ // If --dependency_out was given, this is the path to the file where the
+ // dependency file will be written. Otherwise, empty.
+ string dependency_out_name_;
+
// True if --include_imports was given, meaning that we should
// write all transitive dependencies to the DescriptorSet. Otherwise, only
// the .proto files listed on the command-line are added.
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index dbaaa405..e5b77c33 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -64,6 +64,9 @@
#include <gtest/gtest.h>
+// Disable the whole test when we use tcmalloc for "draconian" heap checks, in
+// which case tcmalloc will print warnings that fail the plugin tests.
+#if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
namespace google {
namespace protobuf {
namespace compiler {
@@ -112,6 +115,16 @@ class CommandLineInterfaceTest : public testing::Test {
// Create a subdirectory within temp_directory_.
void CreateTempDir(const string& name);
+#ifdef PROTOBUF_OPENSOURCE
+ // Change working directory to temp directory.
+ void SwitchToTempDirectory() {
+ File::ChangeWorkingDirectory(temp_directory_);
+ }
+#else // !PROTOBUF_OPENSOURCE
+ // TODO(teboring): Figure out how to change and get working directory in
+ // google3.
+#endif // !PROTOBUF_OPENSOURCE
+
void SetInputsAreProtoPathRelative(bool enable) {
cli_.SetInputsAreProtoPathRelative(enable);
}
@@ -176,6 +189,9 @@ class CommandLineInterfaceTest : public testing::Test {
void ReadDescriptorSet(const string& filename,
FileDescriptorSet* descriptor_set);
+ void ExpectFileContent(const string& filename,
+ const string& content);
+
private:
// The object we are testing.
CommandLineInterface cli_;
@@ -277,6 +293,7 @@ void CommandLineInterfaceTest::Run(const string& command) {
if (!disallow_plugins_) {
cli_.AllowPlugins("prefix-");
+#ifndef GOOGLE_THIRD_PARTY_PROTOBUF
const char* possible_paths[] = {
// When building with shared libraries, libtool hides the real executable
// in .libs and puts a fake wrapper in the current directory.
@@ -305,6 +322,11 @@ void CommandLineInterfaceTest::Run(const string& command) {
}
if (plugin_path.empty()) {
+#else
+ string plugin_path = "third_party/protobuf/test_plugin";
+
+ if (access(plugin_path.c_str(), F_OK) != 0) {
+#endif // GOOGLE_THIRD_PARTY_PROTOBUF
GOOGLE_LOG(ERROR)
<< "Plugin executable not found. Plugin tests are likely to fail.";
} else {
@@ -456,6 +478,17 @@ void CommandLineInterfaceTest::ExpectCapturedStdout(
EXPECT_EQ(expected_text, captured_stdout_);
}
+
+void CommandLineInterfaceTest::ExpectFileContent(
+ const string& filename, const string& content) {
+ string path = temp_directory_ + "/" + filename;
+ string file_contents;
+ GOOGLE_CHECK_OK(File::GetContents(path, &file_contents, true));
+
+ EXPECT_EQ(StringReplace(content, "$tmpdir", temp_directory_, true),
+ file_contents);
+}
+
// ===================================================================
TEST_F(CommandLineInterfaceTest, BasicOutput) {
@@ -940,6 +973,80 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) {
EXPECT_TRUE(descriptor_set.file(1).has_source_code_info());
}
+#ifdef _WIN32
+// TODO(teboring): Figure out how to write test on windows.
+#else
+TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileGivenTwoInputs) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "import \"foo.proto\";\n"
+ "message Bar {\n"
+ " optional Foo foo = 1;\n"
+ "}\n");
+
+ Run("protocol_compiler --dependency_out=$tmpdir/manifest "
+ "--test_out=$tmpdir --proto_path=$tmpdir bar.proto foo.proto");
+
+ ExpectErrorText(
+ "Can only process one input file when using --dependency_out=FILE.\n");
+}
+
+#ifdef PROTOBUF_OPENSOURCE
+TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "import \"foo.proto\";\n"
+ "message Bar {\n"
+ " optional Foo foo = 1;\n"
+ "}\n");
+
+ string current_working_directory = getcwd(NULL, 0);
+ SwitchToTempDirectory();
+
+ Run("protocol_compiler --dependency_out=manifest --test_out=. "
+ "bar.proto");
+
+ ExpectNoErrors();
+
+ ExpectFileContent("manifest",
+ "bar.proto.MockCodeGenerator.test_generator: "
+ "foo.proto\\\n bar.proto");
+
+ File::ChangeWorkingDirectory(current_working_directory);
+}
+#else // !PROTOBUF_OPENSOURCE
+// TODO(teboring): Figure out how to change and get working directory in
+// google3.
+#endif // !PROTOBUF_OPENSOURCE
+
+TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForAbsolutePath) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "import \"foo.proto\";\n"
+ "message Bar {\n"
+ " optional Foo foo = 1;\n"
+ "}\n");
+
+ Run("protocol_compiler --dependency_out=$tmpdir/manifest "
+ "--test_out=$tmpdir --proto_path=$tmpdir bar.proto");
+
+ ExpectNoErrors();
+
+ ExpectFileContent("manifest",
+ "$tmpdir/bar.proto.MockCodeGenerator.test_generator: "
+ "$tmpdir/foo.proto\\\n $tmpdir/bar.proto");
+}
+#endif // !_WIN32
+
// -------------------------------------------------------------------
TEST_F(CommandLineInterfaceTest, ParseErrors) {
@@ -1662,4 +1769,6 @@ TEST_F(EncodeDecodeTest, ProtoParseError) {
} // namespace compiler
} // namespace protobuf
+
+#endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
} // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index 48788197..13ed0b64 100644
--- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -98,7 +98,8 @@ class MockGeneratorContext : public GeneratorContext {
&actual_contents, true));
EXPECT_TRUE(actual_contents == *expected_contents)
<< physical_filename << " needs to be regenerated. Please run "
- "generate_descriptor_proto.sh and add this file "
+ "google/protobuf/compiler/release_compiler.sh and "
+ "generate_descriptor_proto.sh. Then add this file "
"to your CL.";
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 3ce1f120..70d3a600 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -47,7 +47,7 @@ namespace cpp {
namespace {
// The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value
-// is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the
+// is ::google::protobuf::kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the
// generation of the GOOGLE_ARRAYSIZE constant.
bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) {
int32 max_value = descriptor->value(0)->number();
@@ -56,7 +56,7 @@ bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) {
max_value = descriptor->value(i)->number();
}
}
- return max_value != kint32max;
+ return max_value != ::google::protobuf::kint32max;
}
} // namespace
@@ -70,19 +70,30 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
EnumGenerator::~EnumGenerator() {}
+void EnumGenerator::GenerateForwardDeclaration(io::Printer* printer) {
+ if (!options_.proto_h) {
+ return;
+ }
+ map<string, string> vars;
+ vars["classname"] = classname_;
+ printer->Print(vars, "enum $classname$ : int;\n");
+ printer->Print(vars, "bool $classname$_IsValid(int value);\n");
+}
+
void EnumGenerator::GenerateDefinition(io::Printer* printer) {
map<string, string> vars;
vars["classname"] = classname_;
vars["short_name"] = descriptor_->name();
+ vars["enumbase"] = classname_ + (options_.proto_h ? " : int" : "");
- printer->Print(vars, "enum $classname$ {\n");
+ printer->Print(vars, "enum $enumbase$ {\n");
printer->Indent();
const EnumValueDescriptor* min_value = descriptor_->value(0);
const EnumValueDescriptor* max_value = descriptor_->value(0);
for (int i = 0; i < descriptor_->value_count(); i++) {
- vars["name"] = descriptor_->value(i)->name();
+ vars["name"] = EnumValueName(descriptor_->value(i));
// In C++, an value of -2147483648 gets interpreted as the negative of
// 2147483648, and since 2147483648 can't fit in an integer, this produces a
// compiler warning. This works around that issue.
@@ -113,8 +124,8 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
printer->Outdent();
printer->Print("\n};\n");
- vars["min_name"] = min_value->name();
- vars["max_name"] = max_value->name();
+ vars["min_name"] = EnumValueName(min_value);
+ vars["max_name"] = EnumValueName(max_value);
if (options_.dllexport_decl.empty()) {
vars["dllexport"] = "";
@@ -153,9 +164,12 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
void EnumGenerator::
GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
+ printer->Print(
+ "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type "
+ "{};\n",
+ "classname", ClassName(descriptor_, true));
if (HasDescriptorMethods(descriptor_->file())) {
printer->Print(
- "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type {};\n"
"template <>\n"
"inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n"
" return $classname$_descriptor();\n"
@@ -171,7 +185,7 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
printer->Print(vars, "typedef $classname$ $nested_name$;\n");
for (int j = 0; j < descriptor_->value_count(); j++) {
- vars["tag"] = descriptor_->value(j)->name();
+ vars["tag"] = EnumValueName(descriptor_->value(j));
printer->Print(vars,
"static const $nested_name$ $tag$ = $classname$_$tag$;\n");
}
@@ -275,7 +289,7 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) {
vars["parent"] = ClassName(descriptor_->containing_type(), false);
vars["nested_name"] = descriptor_->name();
for (int i = 0; i < descriptor_->value_count(); i++) {
- vars["value"] = descriptor_->value(i)->name();
+ vars["value"] = EnumValueName(descriptor_->value(i));
printer->Print(vars,
"const $classname$ $parent$::$value$;\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h
index 1ebd7cf7..3e930856 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.h
@@ -60,6 +60,12 @@ class EnumGenerator {
// Header stuff.
+ // Generate header code to forward-declare 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 GenerateForwardDeclaration(io::Printer* printer);
+
// Generate header code defining the enum. This code should be placed
// within the enum's package namespace, but NOT within any class, even for
// nested enums.
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 17926135..965327b1 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -76,23 +76,26 @@ GeneratePrivateMembers(io::Printer* printer) const {
void EnumFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "inline $type$ $name$() const$deprecation$;\n"
- "inline void set_$name$($type$ value)$deprecation$;\n");
+ "$type$ $name$() const$deprecation$;\n"
+ "void set_$name$($type$ value)$deprecation$;\n");
}
void EnumFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline $type$ $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ $type$ $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return static_cast< $type$ >($name$_);\n"
"}\n"
- "inline void $classname$::set_$name$($type$ value) {\n");
+ "$inline$ void $classname$::set_$name$($type$ value) {\n");
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
- printer->Print(variables_,
+ printer->Print(variables,
" assert($type$_IsValid(value));\n");
}
- printer->Print(variables_,
+ printer->Print(variables,
" $set_hasbit$\n"
" $name$_ = value;\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
@@ -181,21 +184,24 @@ EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {}
void EnumOneofFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline $type$ $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ $type$ $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" if (has_$name$()) {\n"
" return static_cast< $type$ >($oneof_prefix$$name$_);\n"
" }\n"
" return static_cast< $type$ >($default$);\n"
"}\n"
- "inline void $classname$::set_$name$($type$ value) {\n");
+ "$inline$ void $classname$::set_$name$($type$ value) {\n");
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
- printer->Print(variables_,
+ printer->Print(variables,
" assert($type$_IsValid(value));\n");
}
- printer->Print(variables_,
+ printer->Print(variables,
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -236,7 +242,7 @@ void RepeatedEnumFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_,
"::google::protobuf::RepeatedField<int> $name$_;\n");
- if (descriptor_->options().packed()
+ if (descriptor_->is_packed()
&& HasGeneratedMethods(descriptor_->file())) {
printer->Print(variables_,
"mutable int _$name$_cached_byte_size_;\n");
@@ -246,46 +252,49 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "inline $type$ $name$(int index) const$deprecation$;\n"
- "inline void set_$name$(int index, $type$ value)$deprecation$;\n"
- "inline void add_$name$($type$ value)$deprecation$;\n");
+ "$type$ $name$(int index) const$deprecation$;\n"
+ "void set_$name$(int index, $type$ value)$deprecation$;\n"
+ "void add_$name$($type$ value)$deprecation$;\n");
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
- "inline ::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n");
+ "const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
+ "::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n");
}
void RepeatedEnumFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline $type$ $classname$::$name$(int index) const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ $type$ $classname$::$name$(int index) const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return static_cast< $type$ >($name$_.Get(index));\n"
"}\n"
- "inline void $classname$::set_$name$(int index, $type$ value) {\n");
+ "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n");
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
- printer->Print(variables_,
+ printer->Print(variables,
" assert($type$_IsValid(value));\n");
}
- printer->Print(variables_,
+ printer->Print(variables,
" $name$_.Set(index, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "inline void $classname$::add_$name$($type$ value) {\n");
+ "$inline$ void $classname$::add_$name$($type$ value) {\n");
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
- printer->Print(variables_,
+ printer->Print(variables,
" assert($type$_IsValid(value));\n");
}
- printer->Print(variables_,
+ printer->Print(variables,
" $name$_.Add(value);\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n");
- printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedField<int>&\n"
+ printer->Print(variables,
+ "$inline$ const ::google::protobuf::RepeatedField<int>&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "inline ::google::protobuf::RepeatedField<int>*\n"
+ "$inline$ ::google::protobuf::RepeatedField<int>*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$name$_;\n"
@@ -343,21 +352,35 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
- if (!descriptor_->options().packed()) {
- // We use a non-inlined implementation in this case, since this path will
- // rarely be executed.
- printer->Print(variables_,
- "DO_((::google::protobuf::internal::WireFormatLite::ReadPackedEnumNoInline(\n"
- " input,\n");
+ if (!descriptor_->is_packed()) {
+ // This path is rarely executed, so we use a non-inlined implementation.
if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
printer->Print(variables_,
- " NULL,\n");
+ "DO_((::google::protobuf::internal::"
+ "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
+ " input,\n"
+ " $number$,\n"
+ " NULL,\n"
+ " NULL,\n"
+ " this->mutable_$name$())));\n");
+ } else if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(variables_,
+ "DO_((::google::protobuf::internal::WireFormat::ReadPackedEnumPreserveUnknowns(\n"
+ " input,\n"
+ " $number$,\n"
+ " $type$_IsValid,\n"
+ " mutable_unknown_fields(),\n"
+ " this->mutable_$name$())));\n");
} else {
printer->Print(variables_,
- " &$type$_IsValid,\n");
+ "DO_((::google::protobuf::internal::"
+ "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
+ " input,\n"
+ " $number$,\n"
+ " $type$_IsValid,\n"
+ " &unknown_fields_stream,\n"
+ " this->mutable_$name$())));\n");
}
- printer->Print(variables_,
- " this->mutable_$name$())));\n");
} else {
printer->Print(variables_,
"::google::protobuf::uint32 length;\n"
@@ -376,6 +399,16 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
printer->Print(variables_,
" if ($type$_IsValid(value)) {\n"
" add_$name$(static_cast< $type$ >(value));\n"
+ " } else {\n");
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(variables_,
+ " mutable_unknown_fields()->AddVarint($number$, value);\n");
+ } else {
+ printer->Print(variables_,
+ " unknown_fields_stream.WriteVarint32(tag);\n"
+ " unknown_fields_stream.WriteVarint32(value);\n");
+ }
+ printer->Print(
" }\n");
}
printer->Print(variables_,
@@ -386,7 +419,7 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
// Write the tag and the size.
printer->Print(variables_,
"if (this->$name$_size() > 0) {\n"
@@ -399,7 +432,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
}
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
" ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n"
" this->$name$(i), output);\n");
@@ -413,7 +446,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
// Write the tag and the size.
printer->Print(variables_,
"if (this->$name$_size() > 0) {\n"
@@ -427,7 +460,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
}
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
" target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n"
" this->$name$(i), target);\n");
@@ -451,7 +484,7 @@ GenerateByteSize(io::Printer* printer) const {
" this->$name$(i));\n"
"}\n");
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
"if (data_size > 0) {\n"
" total_size += $tag_size$ +\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
index def2b232..5b1d01ea 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
@@ -53,7 +53,8 @@ class EnumFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
@@ -78,7 +79,8 @@ class EnumOneofFieldGenerator : public EnumFieldGenerator {
~EnumOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
@@ -96,7 +98,8 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index c37fe0be..1d7f8233 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -82,14 +82,40 @@ class FieldGenerator {
// implementation is empty.
virtual void GenerateStaticMembers(io::Printer* /*printer*/) const {}
+ // Generate prototypes for accessors that will manipulate imported
+ // messages inline. These are for .proto.h headers.
+ //
+ // In .proto.h mode, the headers of imports are not #included. However,
+ // functions that manipulate the imported message types need access to
+ // the class definition of the imported message, meaning that the headers
+ // must be #included. To get around this, functions that manipulate
+ // imported message objects are defined as dependent functions in a base
+ // template class. By making them dependent template functions, the
+ // function templates will not be instantiated until they are called, so
+ // we can defer to those translation units to #include the necessary
+ // generated headers.
+ //
+ // See:
+ // http://en.cppreference.com/w/cpp/language/class_template#Implicit_instantiation
+ //
+ // Most field types don't need this, so the default implementation is empty.
+ virtual void GenerateDependentAccessorDeclarations(
+ io::Printer* printer) const {}
+
// Generate prototypes for all of the accessor functions related to this
// field. These are placed inside the class definition.
virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0;
+ // Generate inline definitions of depenent accessor functions for this field.
+ // These are placed inside the header after all class definitions.
+ virtual void GenerateDependentInlineAccessorDefinitions(
+ io::Printer* printer) const {}
+
// Generate inline definitions of accessor functions for this field.
// These are placed inside the header after all class definitions.
+ // In non-.proto.h mode, this generates dependent accessor functions as well.
virtual void GenerateInlineAccessorDefinitions(
- io::Printer* printer) const = 0;
+ io::Printer* printer, bool is_inline) const = 0;
// Generate definitions of accessors that aren't inlined. These are
// placed somewhere in the .cc file.
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index fae4df40..1f0a8205 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -94,99 +94,10 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
FileGenerator::~FileGenerator() {}
void FileGenerator::GenerateHeader(io::Printer* printer) {
- string filename_identifier = FilenameIdentifier(file_->name());
-
- // Generate top of header.
- printer->Print(
- "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
- "// source: $filename$\n"
- "\n"
- "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
- "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
- "\n"
- "#include <string>\n"
- "\n",
- "filename", file_->name(),
- "filename_identifier", filename_identifier);
-
-
- printer->Print(
- "#include <google/protobuf/stubs/common.h>\n"
- "\n");
-
- // Verify the protobuf library header version is compatible with the protoc
- // version before going any further.
- printer->Print(
- "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
- "#error This file was generated by a newer version of protoc which is\n"
- "#error incompatible with your Protocol Buffer headers. Please update\n"
- "#error your headers.\n"
- "#endif\n"
- "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
- "#error This file was generated by an older version of protoc which is\n"
- "#error incompatible with your Protocol Buffer headers. Please\n"
- "#error regenerate this file with a newer version of protoc.\n"
- "#endif\n"
- "\n",
- "min_header_version",
- SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
- "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
-
- // OK, it's now safe to #include other files.
- printer->Print(
- "#include <google/protobuf/arena.h>\n"
- "#include <google/protobuf/arenastring.h>\n"
- "#include <google/protobuf/generated_message_util.h>\n"
- "#include <google/protobuf/metadata.h>\n");
- if (file_->message_type_count() > 0) {
- if (HasDescriptorMethods(file_)) {
- printer->Print(
- "#include <google/protobuf/message.h>\n");
- } else {
- printer->Print(
- "#include <google/protobuf/message_lite.h>\n");
- }
- }
- printer->Print(
- "#include <google/protobuf/repeated_field.h>\n"
- "#include <google/protobuf/extension_set.h>\n");
- if (HasMapFields(file_)) {
- printer->Print(
- "#include <google/protobuf/map.h>\n"
- "#include <google/protobuf/map_field_inl.h>\n");
- }
-
- if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) {
- printer->Print(
- "#include <google/protobuf/generated_enum_reflection.h>\n");
- }
-
- if (HasGenericServices(file_)) {
- printer->Print(
- "#include <google/protobuf/service.h>\n");
- }
-
- if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
- printer->Print(
- "#include <google/protobuf/unknown_field_set.h>\n");
- }
-
-
- set<string> public_import_names;
- for (int i = 0; i < file_->public_dependency_count(); i++) {
- public_import_names.insert(file_->public_dependency(i)->name());
- }
-
- for (int i = 0; i < file_->dependency_count(); i++) {
- const string& name = file_->dependency(i)->name();
- bool public_import = (public_import_names.count(name) != 0);
+ GenerateTopHeaderGuard(printer);
-
- printer->Print(
- "#include \"$dependency$.pb.h\"$iwyu$\n",
- "dependency", StripProto(name),
- "iwyu", (public_import) ? " // IWYU pragma: export" : "");
- }
+ GenerateLibraryIncludes(printer);
+ GenerateDependencyIncludes(printer);
printer->Print(
"// @@protoc_insertion_point(includes)\n");
@@ -196,130 +107,44 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
// Open namespace.
GenerateNamespaceOpeners(printer);
- // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
- // functions, so that we can declare them to be friends of each class.
- printer->Print(
- "\n"
- "// Internal implementation detail -- do not call these.\n"
- "void $dllexport_decl$$adddescriptorsname$();\n",
- "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
- "dllexport_decl",
- options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
-
- printer->Print(
- // Note that we don't put dllexport_decl on these because they are only
- // called by the .pb.cc file in which they are defined.
- "void $assigndescriptorsname$();\n"
- "void $shutdownfilename$();\n"
- "\n",
- "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
- "shutdownfilename", GlobalShutdownFileName(file_->name()));
-
- // Generate forward declarations of classes.
- for (int i = 0; i < file_->message_type_count(); i++) {
- message_generators_[i]->GenerateForwardDeclaration(printer);
- }
+ GenerateGlobalStateFunctionDeclarations(printer);
+ GenerateMessageForwardDeclarations(printer);
printer->Print("\n");
- // Generate enum definitions.
- for (int i = 0; i < file_->message_type_count(); i++) {
- message_generators_[i]->GenerateEnumDefinitions(printer);
- }
- for (int i = 0; i < file_->enum_type_count(); i++) {
- enum_generators_[i]->GenerateDefinition(printer);
- }
+ GenerateEnumDefinitions(printer);
printer->Print(kThickSeparator);
printer->Print("\n");
- // Generate class definitions.
- for (int i = 0; i < file_->message_type_count(); i++) {
- if (i > 0) {
- printer->Print("\n");
- printer->Print(kThinSeparator);
- printer->Print("\n");
- }
- message_generators_[i]->GenerateClassDefinition(printer);
- }
+ GenerateMessageDefinitions(printer);
printer->Print("\n");
printer->Print(kThickSeparator);
printer->Print("\n");
- if (HasGenericServices(file_)) {
- // Generate service definitions.
- for (int i = 0; i < file_->service_count(); i++) {
- if (i > 0) {
- printer->Print("\n");
- printer->Print(kThinSeparator);
- printer->Print("\n");
- }
- service_generators_[i]->GenerateDeclarations(printer);
- }
+ GenerateServiceDefinitions(printer);
- printer->Print("\n");
- printer->Print(kThickSeparator);
- printer->Print("\n");
- }
-
- // Declare extension identifiers.
- for (int i = 0; i < file_->extension_count(); i++) {
- extension_generators_[i]->GenerateDeclaration(printer);
- }
+ GenerateExtensionIdentifiers(printer);
printer->Print("\n");
printer->Print(kThickSeparator);
printer->Print("\n");
-
- // Generate class inline methods.
- for (int i = 0; i < file_->message_type_count(); i++) {
- if (i > 0) {
- printer->Print(kThinSeparator);
- printer->Print("\n");
- }
- message_generators_[i]->GenerateInlineMethods(printer);
- }
-
- printer->Print(
- "\n"
- "// @@protoc_insertion_point(namespace_scope)\n");
+ GenerateInlineFunctionDefinitions(printer);
// Close up namespace.
GenerateNamespaceClosers(printer);
- // Emit GetEnumDescriptor specializations into google::protobuf namespace:
- if (HasDescriptorMethods(file_)) {
- // The SWIG conditional is to avoid a null-pointer dereference
- // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
- // namespace X { void Y<Z::W>(); }
- // which appears in GetEnumDescriptor() specializations.
- printer->Print(
- "\n"
- "#ifndef SWIG\n"
- "namespace google {\nnamespace protobuf {\n"
- "\n");
- for (int i = 0; i < file_->message_type_count(); i++) {
- message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
- }
- for (int i = 0; i < file_->enum_type_count(); i++) {
- enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
- }
- printer->Print(
- "\n"
- "} // namespace protobuf\n} // namespace google\n"
- "#endif // SWIG\n");
- }
+ // We need to specialize some templates in the ::google::protobuf namespace:
+ GenerateProto2NamespaceEnumSpecializations(printer);
printer->Print(
"\n"
"// @@protoc_insertion_point(global_scope)\n"
"\n");
- printer->Print(
- "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
- "filename_identifier", filename_identifier);
+ GenerateBottomHeaderGuard(printer);
}
void FileGenerator::GenerateSource(io::Printer* printer) {
@@ -417,6 +242,12 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
printer->Print(kThickSeparator);
printer->Print("\n");
message_generators_[i]->GenerateClassMethods(printer);
+
+ printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n");
+ // Generate class inline methods.
+ message_generators_[i]->GenerateInlineMethods(printer,
+ /* is_inline = */ false);
+ printer->Print("#endif // PROTOBUF_INLINE_NOT_IN_HEADERS\n");
}
if (HasGenericServices(file_)) {
@@ -603,20 +434,52 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
string file_data;
file_proto.SerializeToString(&file_data);
- printer->Print(
- "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
-
- // Only write 40 bytes per line.
- static const int kBytesPerLine = 40;
- for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
- printer->Print("\n \"$data$\"",
- "data",
- EscapeTrigraphs(
- CEscape(file_data.substr(i, kBytesPerLine))));
+ // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535
+ // bytes in length". Declare a static array of characters rather than use a
+ // string literal.
+ if (file_data.size() > 65535) {
+ printer->Print(
+ "static const char descriptor[] = {\n");
+ printer->Indent();
+
+ // Only write 25 bytes per line.
+ static const int kBytesPerLine = 25;
+ for (int i = 0; i < file_data.size();) {
+ for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
+ printer->Print(
+ "$char$, ",
+ "char", SimpleItoa(file_data[i]));
+ }
+ printer->Print(
+ "\n");
+ }
+
+ printer->Outdent();
+ printer->Print(
+ "};\n");
+
+ printer->Print(
+ "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n",
+ "size", SimpleItoa(file_data.size()));
+
+ } else {
+
+ printer->Print(
+ "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
+
+ // Only write 40 bytes per line.
+ static const int kBytesPerLine = 40;
+ for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
+ printer->Print("\n \"$data$\"",
+ "data",
+ EscapeTrigraphs(
+ CEscape(file_data.substr(i, kBytesPerLine))));
+ }
+ printer->Print(
+ ", $size$);\n",
+ "size", SimpleItoa(file_data.size()));
+
}
- printer->Print(
- ", $size$);\n",
- "size", SimpleItoa(file_data.size()));
// Call MessageFactory::InternalRegisterGeneratedFile().
printer->Print(
@@ -685,6 +548,294 @@ void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
}
}
+void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer) {
+ string filename_identifier = FilenameIdentifier(file_->name());
+ // Generate top of header.
+ printer->Print(
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
+ "\n"
+ "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
+ "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
+ "\n"
+ "#include <string>\n"
+ "\n",
+ "filename", file_->name(),
+ "filename_identifier", filename_identifier);
+}
+
+void FileGenerator::GenerateBottomHeaderGuard(io::Printer* printer) {
+ string filename_identifier = FilenameIdentifier(file_->name());
+ printer->Print(
+ "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
+ "filename_identifier", filename_identifier);
+}
+
+void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
+
+ printer->Print(
+ "#include <google/protobuf/stubs/common.h>\n"
+ "\n");
+
+ // Verify the protobuf library header version is compatible with the protoc
+ // version before going any further.
+ printer->Print(
+ "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
+ "#error This file was generated by a newer version of protoc which is\n"
+ "#error incompatible with your Protocol Buffer headers. Please update\n"
+ "#error your headers.\n"
+ "#endif\n"
+ "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
+ "#error This file was generated by an older version of protoc which is\n"
+ "#error incompatible with your Protocol Buffer headers. Please\n"
+ "#error regenerate this file with a newer version of protoc.\n"
+ "#endif\n"
+ "\n",
+ "min_header_version",
+ SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
+ "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
+
+ // OK, it's now safe to #include other files.
+ printer->Print(
+ "#include <google/protobuf/arena.h>\n"
+ "#include <google/protobuf/arenastring.h>\n"
+ "#include <google/protobuf/generated_message_util.h>\n");
+ if (UseUnknownFieldSet(file_)) {
+ printer->Print(
+ "#include <google/protobuf/metadata.h>\n");
+ }
+ if (file_->message_type_count() > 0) {
+ if (HasDescriptorMethods(file_)) {
+ printer->Print(
+ "#include <google/protobuf/message.h>\n");
+ } else {
+ printer->Print(
+ "#include <google/protobuf/message_lite.h>\n");
+ }
+ }
+ printer->Print(
+ "#include <google/protobuf/repeated_field.h>\n"
+ "#include <google/protobuf/extension_set.h>\n");
+ if (HasMapFields(file_)) {
+ printer->Print(
+ "#include <google/protobuf/map.h>\n");
+ if (HasDescriptorMethods(file_)) {
+ printer->Print(
+ "#include <google/protobuf/map_field_inl.h>\n");
+ } else {
+ printer->Print(
+ "#include <google/protobuf/map_field_lite.h>\n");
+ }
+ }
+
+ if (HasEnumDefinitions(file_)) {
+ if (HasDescriptorMethods(file_)) {
+ printer->Print(
+ "#include <google/protobuf/generated_enum_reflection.h>\n");
+ } else {
+ printer->Print(
+ "#include <google/protobuf/generated_enum_util.h>\n");
+ }
+ }
+
+ if (HasGenericServices(file_)) {
+ printer->Print(
+ "#include <google/protobuf/service.h>\n");
+ }
+
+ if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
+ printer->Print(
+ "#include <google/protobuf/unknown_field_set.h>\n");
+ }
+
+
+ if (IsAnyMessage(file_)) {
+ printer->Print(
+ "#include \"google/protobuf/any.h\"\n");
+ }
+}
+
+void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
+ set<string> public_import_names;
+ for (int i = 0; i < file_->public_dependency_count(); i++) {
+ public_import_names.insert(file_->public_dependency(i)->name());
+ }
+
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ const string& name = file_->dependency(i)->name();
+ bool public_import = (public_import_names.count(name) != 0);
+
+
+ printer->Print(
+ "#include \"$dependency$.pb.h\"$iwyu$\n",
+ "dependency", StripProto(name),
+ "iwyu", (public_import) ? " // IWYU pragma: export" : "");
+ }
+}
+
+void FileGenerator::GenerateGlobalStateFunctionDeclarations(
+ io::Printer* printer) {
+ // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
+ // functions, so that we can declare them to be friends of each class.
+ printer->Print(
+ "\n"
+ "// Internal implementation detail -- do not call these.\n"
+ "void $dllexport_decl$$adddescriptorsname$();\n",
+ "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
+ "dllexport_decl",
+ options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
+
+ printer->Print(
+ // Note that we don't put dllexport_decl on these because they are only
+ // called by the .pb.cc file in which they are defined.
+ "void $assigndescriptorsname$();\n"
+ "void $shutdownfilename$();\n"
+ "\n",
+ "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
+ "shutdownfilename", GlobalShutdownFileName(file_->name()));
+}
+
+void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) {
+ // Generate forward declarations of classes.
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->GenerateMessageForwardDeclaration(printer);
+ }
+}
+
+void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
+ // Generate class definitions.
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ if (i > 0) {
+ printer->Print("\n");
+ printer->Print(kThinSeparator);
+ printer->Print("\n");
+ }
+ message_generators_[i]->GenerateClassDefinition(printer);
+ }
+}
+
+void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
+ // Generate enum definitions.
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->GenerateEnumDefinitions(printer);
+ }
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ enum_generators_[i]->GenerateDefinition(printer);
+ }
+}
+
+void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
+ if (HasGenericServices(file_)) {
+ // Generate service definitions.
+ for (int i = 0; i < file_->service_count(); i++) {
+ if (i > 0) {
+ printer->Print("\n");
+ printer->Print(kThinSeparator);
+ printer->Print("\n");
+ }
+ service_generators_[i]->GenerateDeclarations(printer);
+ }
+
+ printer->Print("\n");
+ printer->Print(kThickSeparator);
+ printer->Print("\n");
+ }
+}
+
+void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) {
+ // Declare extension identifiers.
+ for (int i = 0; i < file_->extension_count(); i++) {
+ extension_generators_[i]->GenerateDeclaration(printer);
+ }
+}
+
+void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
+ // An aside about inline functions in .proto.h mode:
+ //
+ // The PROTOBUF_INLINE_NOT_IN_HEADERS symbol controls conditionally
+ // moving much of the inline functions to the .pb.cc file, which can be a
+ // significant performance benefit for compilation time, at the expense
+ // of non-inline function calls.
+ //
+ // However, in .proto.h mode, the definition of the internal dependent
+ // base class must remain in the header, and can never be out-lined. The
+ // dependent base class also needs access to has-bit manipuation
+ // functions, so the has-bit functions must be unconditionally inlined in
+ // proto_h mode.
+ //
+ // This gives us three flavors of functions:
+ //
+ // 1. Functions on the message not used by the internal dependent base
+ // class: in .proto.h mode, only some functions are defined on the
+ // message class; others are defined on the dependent base class.
+ // These are guarded and can be out-lined. These are generated by
+ // GenerateInlineMethods, and include has_* bit functions in
+ // non-proto_h mode.
+ //
+ // 2. Functions on the internal dependent base class: these functions
+ // are dependent on a template parameter, so they always need to
+ // remain in the header.
+ //
+ // 3. Functions on the message that are used by the dependent base: the
+ // dependent base class down casts itself to the message
+ // implementation class to access these functions (the has_* bit
+ // manipulation functions). Unlike #1, these functions must
+ // unconditionally remain in the header. These are emitted by
+ // GenerateDependentInlineMethods, even though they are not actually
+ // dependent.
+
+ printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
+ // Generate class inline methods.
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ if (i > 0) {
+ printer->Print(kThinSeparator);
+ printer->Print("\n");
+ }
+ message_generators_[i]->GenerateInlineMethods(printer,
+ /* is_inline = */ true);
+ }
+ printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
+
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ if (i > 0) {
+ printer->Print(kThinSeparator);
+ printer->Print("\n");
+ }
+ // Methods of the dependent base class must always be inline in the header.
+ message_generators_[i]->GenerateDependentInlineMethods(printer);
+ }
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n");
+}
+
+void FileGenerator::GenerateProto2NamespaceEnumSpecializations(
+ io::Printer* printer) {
+ // Emit GetEnumDescriptor specializations into google::protobuf namespace:
+ if (HasEnumDefinitions(file_)) {
+ // The SWIG conditional is to avoid a null-pointer dereference
+ // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
+ // namespace X { void Y<Z::W>(); }
+ // which appears in GetEnumDescriptor() specializations.
+ printer->Print(
+ "\n"
+ "#ifndef SWIG\n"
+ "namespace google {\nnamespace protobuf {\n"
+ "\n");
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
+ }
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
+ }
+ printer->Print(
+ "\n"
+ "} // namespace protobuf\n} // namespace google\n"
+ "#endif // SWIG\n");
+ }
+}
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h
index 0e06547d..e68f67bb 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -80,6 +80,35 @@ class FileGenerator {
void GenerateNamespaceOpeners(io::Printer* printer);
void GenerateNamespaceClosers(io::Printer* printer);
+ // Generates top or bottom of a header file.
+ void GenerateTopHeaderGuard(io::Printer* printer);
+ void GenerateBottomHeaderGuard(io::Printer* printer);
+
+ // Generates #include directives.
+ void GenerateLibraryIncludes(io::Printer* printer);
+ void GenerateDependencyIncludes(io::Printer* printer);
+
+ // Generates a couple of different pieces before definitions:
+ void GenerateGlobalStateFunctionDeclarations(io::Printer* printer);
+
+ // Generates types for classes.
+ void GenerateMessageForwardDeclarations(io::Printer* printer);
+ void GenerateMessageDefinitions(io::Printer* printer);
+
+ // Generates enum definitions.
+ void GenerateEnumDefinitions(io::Printer* printer);
+
+ // Generates generic service definitions.
+ void GenerateServiceDefinitions(io::Printer* printer);
+
+ // Generates extension identifiers.
+ void GenerateExtensionIdentifiers(io::Printer* printer);
+
+ // Generates inline function defintions.
+ void GenerateInlineFunctionDefinitions(io::Printer* printer);
+
+ void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer);
+
const FileDescriptor* file_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > message_generators_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index c999b93f..99416372 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -82,6 +82,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
// }
// FOO_EXPORT is a macro which should expand to __declspec(dllexport) or
// __declspec(dllimport) depending on what is being compiled.
+ //
Options file_options;
for (int i = 0; i < options.size(); i++) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 28c4dd54..0f3688d0 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -51,6 +51,9 @@ namespace cpp {
namespace {
+static const char kAnyMessageName[] = "Any";
+static const char kAnyProtoFile[] = "google/protobuf/any.proto";
+
string DotsToUnderscores(const string& name) {
return StringReplace(name, ".", "_", true);
}
@@ -162,6 +165,10 @@ string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
}
+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";
@@ -176,6 +183,14 @@ string FieldName(const FieldDescriptor* field) {
return result;
}
+string EnumValueName(const EnumValueDescriptor* enum_value) {
+ string result = enum_value->name();
+ if (kKeywords.count(result) > 0) {
+ result.append("_");
+ }
+ return result;
+}
+
string FieldConstantName(const FieldDescriptor *field) {
string field_name = UnderscoresToCamelCase(field->name(), true);
string result = "k" + field_name + "FieldNumber";
@@ -192,6 +207,47 @@ string FieldConstantName(const FieldDescriptor *field) {
return result;
}
+bool IsFieldDependent(const FieldDescriptor* field) {
+ if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+ return false;
+ }
+ if (field->containing_oneof() != NULL) {
+ // Oneof fields will always be dependent.
+ //
+ // This is a unique case for field codegen. Field generators are
+ // responsible for generating all the field-specific accessor
+ // functions, except for the clear_*() function; instead, field
+ // generators produce inline clearing code.
+ //
+ // For non-oneof fields, the Message class uses the inline clearing
+ // code to define the field's clear_*() function, as well as in the
+ // destructor. For oneof fields, the Message class generates a much
+ // more complicated clear_*() function, which clears only the oneof
+ // member that is set, in addition to clearing methods for each of the
+ // oneof members individually.
+ //
+ // Since oneofs do not have their own generator class, the Message code
+ // generation logic would be significantly complicated in order to
+ // split dependent and non-dependent manipulation logic based on
+ // whether the oneof truly needs to be dependent; so, for oneof fields,
+ // we just assume it (and its constituents) should be manipulated by a
+ // dependent base class function.
+ //
+ // This is less precise than how dependent message-typed fields are
+ // handled, but the cost is limited to only the generated code for the
+ // oneof field, which seems like an acceptable tradeoff.
+ return true;
+ }
+ if (field->file() == field->message_type()->file()) {
+ return false;
+ }
+ return true;
+}
+
+string DependentTypeName(const FieldDescriptor* field) {
+ return "InternalBase_" + field->name() + "_T";
+}
+
string FieldMessageTypeName(const FieldDescriptor* field) {
// Note: The Google-internal version of Protocol Buffers uses this function
// as a hook point for hacks to support legacy code.
@@ -352,9 +408,7 @@ string FilenameIdentifier(const string& filename) {
} else {
// Not alphanumeric. To avoid any possibility of name conflicts we
// use the hex code for the character.
- result.push_back('_');
- char buffer[kFastToBufferSize];
- result.append(FastHexToBuffer(static_cast<uint8>(filename[i]), buffer));
+ StrAppend(&result, "_", strings::Hex(static_cast<uint8>(filename[i])));
}
}
return result;
@@ -508,6 +562,22 @@ bool IsStringOrMessage(const FieldDescriptor* field) {
return false;
}
+FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field) {
+ GOOGLE_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING);
+ // Open-source protobuf release only supports STRING ctype.
+ return FieldOptions::STRING;
+
+}
+
+bool IsAnyMessage(const FileDescriptor* descriptor) {
+ return descriptor->name() == kAnyProtoFile;
+}
+
+bool IsAnyMessage(const Descriptor* descriptor) {
+ return descriptor->name() == kAnyMessageName &&
+ descriptor->file()->name() == kAnyProtoFile;
+}
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index e60fa7c2..4bbf8303 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -66,6 +66,10 @@ extern const char kThinSeparator[];
string ClassName(const Descriptor* descriptor, bool qualified);
string ClassName(const EnumDescriptor* enum_descriptor, bool qualified);
+// Name of the CRTP class template (for use with proto_h).
+// This is a class name, like "ProtoName_InternalBase".
+string DependentBaseClassTemplateName(const Descriptor* descriptor);
+
string SuperClassName(const Descriptor* descriptor);
// Get the (unqualified) name that should be used for this field in C++ code.
@@ -74,6 +78,9 @@ string SuperClassName(const Descriptor* descriptor);
// anyway, so normally this just returns field->name().
string FieldName(const FieldDescriptor* field);
+// Get the sanitized name that should be used for the given enum in C++ code.
+string EnumValueName(const EnumValueDescriptor* enum_value);
+
// Get the unqualified name that should be used for a field's field
// number constant.
string FieldConstantName(const FieldDescriptor *field);
@@ -85,6 +92,20 @@ inline const Descriptor* FieldScope(const FieldDescriptor* field) {
field->extension_scope() : field->containing_type();
}
+// Returns true if the given 'field_descriptor' has a message type that is
+// a dependency of the file where the field is defined (i.e., the field
+// type is defined in a different file than the message holding the field).
+//
+// This only applies to Message-typed fields. Enum-typed fields may refer
+// to an enum in a dependency; however, enums are specified and
+// forward-declared with an enum-base, so the definition is not required to
+// manipulate the field value.
+bool IsFieldDependent(const FieldDescriptor* field_descriptor);
+
+// Returns the name that should be used for forcing dependent lookup from a
+// dependent base class.
+string DependentTypeName(const FieldDescriptor* field);
+
// Returns the fully-qualified type name field->message_type(). Usually this
// is just ClassName(field->message_type(), true);
string FieldMessageTypeName(const FieldDescriptor* field);
@@ -211,6 +232,10 @@ inline bool IsMapEntryMessage(const Descriptor* descriptor) {
// Returns true if the field's CPPTYPE is string or message.
bool IsStringOrMessage(const FieldDescriptor* field);
+// For a string field, returns the effective ctype. If the actual ctype is
+// not supported, returns the default of STRING.
+FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field);
+
string UnderscoresToCamelCase(const string& input, bool cap_next_letter);
inline bool HasFieldPresence(const FileDescriptor* file) {
@@ -235,6 +260,9 @@ inline bool SupportsArenas(const FieldDescriptor* field) {
return SupportsArenas(field->file());
}
+bool IsAnyMessage(const FileDescriptor* descriptor);
+bool IsAnyMessage(const Descriptor* descriptor);
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index 0154eeb8..0ff0d27c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -31,6 +31,7 @@
#include <google/protobuf/compiler/cpp/cpp_map_field.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
@@ -72,14 +73,21 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
(*variables)["val_cpp"] = PrimitiveTypeName(val->cpp_type());
(*variables)["wrapper"] = "EntryWrapper";
}
- (*variables)["key_type"] =
- "::google::protobuf::FieldDescriptor::TYPE_" +
+ (*variables)["key_wire_type"] =
+ "::google::protobuf::internal::WireFormatLite::TYPE_" +
ToUpper(DeclaredTypeMethodName(key->type()));
- (*variables)["val_type"] =
- "::google::protobuf::FieldDescriptor::TYPE_" +
+ (*variables)["val_wire_type"] =
+ "::google::protobuf::internal::WireFormatLite::TYPE_" +
ToUpper(DeclaredTypeMethodName(val->type()));
(*variables)["map_classname"] = ClassName(descriptor->message_type(), false);
- (*variables)["number"] = Int32ToString(descriptor->number());
+ (*variables)["number"] = SimpleItoa(descriptor->number());
+ (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
+
+ if (HasDescriptorMethods(descriptor->file())) {
+ (*variables)["lite"] = "";
+ } else {
+ (*variables)["lite"] = "Lite";
+ }
if (!IsProto3Field(descriptor) &&
val->type() == FieldDescriptor::TYPE_ENUM) {
@@ -102,33 +110,40 @@ MapFieldGenerator::~MapFieldGenerator() {}
void MapFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "typedef ::google::protobuf::internal::MapEntry<\n"
+ "typedef ::google::protobuf::internal::MapEntryLite<\n"
" $key_cpp$, $val_cpp$,\n"
- " $key_type$,\n"
- " $val_type$, $default_enum_value$>\n"
+ " $key_wire_type$,\n"
+ " $val_wire_type$,\n"
+ " $default_enum_value$ >\n"
" $map_classname$;\n"
- "::google::protobuf::internal::MapField< $key_cpp$, $val_cpp$,"
- "$key_type$, $val_type$, $default_enum_value$ > $name$_;\n");
+ "::google::protobuf::internal::MapField$lite$<\n"
+ " $key_cpp$, $val_cpp$,\n"
+ " $key_wire_type$,\n"
+ " $val_wire_type$,\n"
+ " $default_enum_value$ > $name$_;\n");
}
void MapFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
+ "const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
" $name$() const$deprecation$;\n"
- "inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
+ "::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
" mutable_$name$()$deprecation$;\n");
}
void MapFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_map:$full_name$)\n"
" return $name$_.GetMap();\n"
"}\n"
- "inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
+ "$inline$ ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_map:$full_name$)\n"
" return $name$_.MutableMap();\n"
@@ -198,11 +213,29 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
" if ($val_cpp$_IsValid(*entry->mutable_value())) {\n"
" (*mutable_$name$())[entry->key()] =\n"
" static_cast<$val_cpp$>(*entry->mutable_value());\n"
- " } else {\n"
- " mutable_unknown_fields()->AddLengthDelimited($number$, data);\n"
+ " } else {\n");
+ if (HasDescriptorMethods(descriptor_->file())) {
+ printer->Print(variables_,
+ " mutable_unknown_fields()"
+ "->AddLengthDelimited($number$, data);\n");
+ } else {
+ printer->Print(variables_,
+ " unknown_fields_stream.WriteVarint32($tag$);\n"
+ " unknown_fields_stream.WriteVarint32(data.size());\n"
+ " unknown_fields_stream.WriteString(data);\n");
+ }
+
+
+ printer->Print(variables_,
" }\n"
"}\n");
}
+
+ // If entry is allocated by arena, its desctructor should be avoided.
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "if (entry->GetArena() != NULL) entry.release();\n");
+ }
}
void MapFieldGenerator::
@@ -211,12 +244,32 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
"{\n"
" ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
" for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
- " it = $name$().begin(); it != $name$().end(); ++it) {\n"
+ " it = this->$name$().begin();\n"
+ " it != this->$name$().end(); ++it) {\n");
+
+ // If entry is allocated by arena, its desctructor should be avoided.
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+ " entry.release();\n"
+ " }\n");
+ }
+
+ printer->Print(variables_,
" entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
" ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
" $number$, *entry, output);\n"
- " }\n"
- "}\n");
+ " }\n");
+
+ // If entry is allocated by arena, its desctructor should be avoided.
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+ " entry.release();\n"
+ " }\n");
+ }
+
+ printer->Print("}\n");
}
void MapFieldGenerator::
@@ -225,13 +278,33 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
"{\n"
" ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
" for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
- " it = $name$().begin(); it != $name$().end(); ++it) {\n"
+ " it = this->$name$().begin();\n"
+ " it != this->$name$().end(); ++it) {\n");
+
+ // If entry is allocated by arena, its desctructor should be avoided.
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+ " entry.release();\n"
+ " }\n");
+ }
+
+ printer->Print(variables_,
" entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
" target = ::google::protobuf::internal::WireFormatLite::\n"
" Write$declared_type$NoVirtualToArray(\n"
" $number$, *entry, target);\n"
- " }\n"
- "}\n");
+ " }\n");
+
+ // If entry is allocated by arena, its desctructor should be avoided.
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+ " entry.release();\n"
+ " }\n");
+ }
+
+ printer->Print("}\n");
}
void MapFieldGenerator::
@@ -241,12 +314,32 @@ GenerateByteSize(io::Printer* printer) const {
"{\n"
" ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
" for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
- " it = $name$().begin(); it != $name$().end(); ++it) {\n"
+ " it = this->$name$().begin();\n"
+ " it != this->$name$().end(); ++it) {\n");
+
+ // If entry is allocated by arena, its desctructor should be avoided.
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+ " entry.release();\n"
+ " }\n");
+ }
+
+ printer->Print(variables_,
" entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
" total_size += ::google::protobuf::internal::WireFormatLite::\n"
" $declared_type$SizeNoVirtual(*entry);\n"
- " }\n"
- "}\n");
+ " }\n");
+
+ // If entry is allocated by arena, its desctructor should be avoided.
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+ " entry.release();\n"
+ " }\n");
+ }
+
+ printer->Print("}\n");
}
} // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h
index 0ff032fd..d27d4851 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h
@@ -50,7 +50,8 @@ class MapFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index e71d35fa..b0e38755 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -64,10 +64,15 @@ using internal::WireFormatLite;
namespace {
-void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) {
- // Print the field's proto-syntax definition as a comment. We don't want to
- // print group bodies so we cut off after the first line.
- string def = field->DebugString();
+template <class T>
+void PrintFieldComment(io::Printer* printer, const T* field) {
+ // Print the field's (or oneof's) proto-syntax definition as a comment.
+ // We don't want to print group bodies so we cut off after the first
+ // line.
+ DebugStringOptions options;
+ options.elide_group_body = true;
+ options.elide_oneof_body = true;
+ string def = field->DebugStringWithOptions(options);
printer->Print("// $def$\n",
"def", def.substr(0, def.find_first_of('\n')));
}
@@ -87,8 +92,8 @@ const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
for (int i = 0; i < descriptor->field_count(); i++) {
fields[i] = descriptor->field(i);
}
- sort(fields, fields + descriptor->field_count(),
- FieldOrderingByNumber());
+ std::sort(fields, fields + descriptor->field_count(),
+ FieldOrderingByNumber());
return fields;
}
@@ -253,7 +258,7 @@ void OptimizePadding(vector<const FieldDescriptor*>* fields) {
// Sort by preferred location to keep fields as close to their original
// location as possible. Using stable_sort ensures that the output is
// consistent across runs.
- stable_sort(aligned_to_4.begin(), aligned_to_4.end());
+ std::stable_sort(aligned_to_4.begin(), aligned_to_4.end());
// Now group fields aligned to 4 bytes (or the 4-field groups created above)
// into pairs, and treat those like a single field aligned to 8 bytes.
@@ -269,7 +274,7 @@ void OptimizePadding(vector<const FieldDescriptor*>* fields) {
aligned_to_8.push_back(field_group);
}
// Sort by preferred location.
- stable_sort(aligned_to_8.begin(), aligned_to_8.end());
+ std::stable_sort(aligned_to_8.begin(), aligned_to_8.end());
// Now pull out all the FieldDescriptors in order.
fields->clear();
@@ -351,11 +356,11 @@ void CollectMapInfo(const Descriptor* descriptor,
default:
(*variables)["val"] = PrimitiveTypeName(val->cpp_type());
}
- (*variables)["key_type"] =
- "::google::protobuf::FieldDescriptor::TYPE_" +
+ (*variables)["key_wire_type"] =
+ "::google::protobuf::internal::WireFormatLite::TYPE_" +
ToUpper(DeclaredTypeMethodName(key->type()));
- (*variables)["val_type"] =
- "::google::protobuf::FieldDescriptor::TYPE_" +
+ (*variables)["val_wire_type"] =
+ "::google::protobuf::internal::WireFormatLite::TYPE_" +
ToUpper(DeclaredTypeMethodName(val->type()));
}
@@ -383,7 +388,8 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
enum_generators_(
new google::protobuf::scoped_ptr<EnumGenerator>[descriptor->enum_type_count()]),
extension_generators_(new google::protobuf::scoped_ptr<
- ExtensionGenerator>[descriptor->extension_count()]) {
+ ExtensionGenerator>[descriptor->extension_count()]),
+ use_dependent_base_(false) {
for (int i = 0; i < descriptor->nested_type_count(); i++) {
nested_generators_[i].reset(
@@ -405,13 +411,16 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
if (descriptor->field(i)->is_required()) {
++num_required_fields_;
}
+ if (options.proto_h && IsFieldDependent(descriptor->field(i))) {
+ use_dependent_base_ = true;
+ }
}
}
MessageGenerator::~MessageGenerator() {}
void MessageGenerator::
-GenerateForwardDeclaration(io::Printer* printer) {
+GenerateMessageForwardDeclaration(io::Printer* printer) {
printer->Print("class $classname$;\n",
"classname", classname_);
@@ -420,7 +429,17 @@ GenerateForwardDeclaration(io::Printer* printer) {
// message cannot be a top level class, we just need to avoid calling
// GenerateForwardDeclaration here.
if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
- nested_generators_[i]->GenerateForwardDeclaration(printer);
+ nested_generators_[i]->GenerateMessageForwardDeclaration(printer);
+ }
+}
+
+void MessageGenerator::
+GenerateEnumForwardDeclaration(io::Printer* printer) {
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ nested_generators_[i]->GenerateEnumForwardDeclaration(printer);
+ }
+ for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+ enum_generators_[i]->GenerateForwardDeclaration(printer);
}
}
@@ -446,6 +465,35 @@ GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
}
void MessageGenerator::
+GenerateDependentFieldAccessorDeclarations(io::Printer* printer) {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+
+ PrintFieldComment(printer, field);
+
+ map<string, string> vars;
+ SetCommonFieldVariables(field, &vars, options_);
+
+ if (use_dependent_base_ && IsFieldDependent(field)) {
+ // 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");
+ }
+ // Generate type-specific accessor declarations.
+ field_generators_.get(field).GenerateDependentAccessorDeclarations(printer);
+ printer->Print("\n");
+ }
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+ PrintFieldComment(printer, oneof);
+ printer->Print(
+ "void clear_$oneof_name$();\n",
+ "oneof_name", oneof->name());
+ }
+}
+
+void MessageGenerator::
GenerateFieldAccessorDeclarations(io::Printer* printer) {
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
@@ -456,18 +504,35 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
SetCommonFieldVariables(field, &vars, options_);
vars["constant_name"] = FieldConstantName(field);
+ bool dependent_field = use_dependent_base_ && IsFieldDependent(field);
+ if (dependent_field) {
+ // If this field is dependent, the dependent base class determines
+ // the message type from the derived class (which is a template
+ // parameter). This typedef is for that:
+ printer->Print(
+ "private:\n"
+ "typedef $field_type$ $dependent_type$;\n"
+ "public:\n",
+ "field_type", FieldMessageTypeName(field),
+ "dependent_type", DependentTypeName(field));
+ }
+
if (field->is_repeated()) {
- printer->Print(vars, "inline int $name$_size() const$deprecation$;\n");
+ printer->Print(vars, "int $name$_size() const$deprecation$;\n");
} else if (HasHasMethod(field)) {
- printer->Print(vars, "inline bool has_$name$() const$deprecation$;\n");
+ printer->Print(vars, "bool has_$name$() const$deprecation$;\n");
} else if (HasPrivateHasMethod(field)) {
printer->Print(vars,
"private:\n"
- "inline bool has_$name$() const$deprecation$;\n"
+ "bool has_$name$() const$deprecation$;\n"
"public:\n");
}
- printer->Print(vars, "inline void clear_$name$()$deprecation$;\n");
+ 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, "static const int $constant_name$ = $number$;\n");
// Generate type-specific accessor declarations.
@@ -486,7 +551,7 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
printer->Print(
- "inline $camel_oneof_name$Case $oneof_name$_case() const;\n",
+ "$camel_oneof_name$Case $oneof_name$_case() const;\n",
"camel_oneof_name",
UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true),
"oneof_name", descriptor_->oneof_decl(i)->name());
@@ -494,7 +559,189 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
}
void MessageGenerator::
-GenerateFieldAccessorDefinitions(io::Printer* printer) {
+GenerateDependentFieldAccessorDefinitions(io::Printer* printer) {
+ if (!use_dependent_base_) return;
+
+ printer->Print("// $classname$\n\n", "classname",
+ DependentBaseClassTemplateName(descriptor_));
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+
+ PrintFieldComment(printer, field);
+
+ // These functions are not really dependent: they are part of the
+ // (non-dependent) derived class. However, they need to live outside
+ // any #ifdef guards, so we treat them as if they were dependent.
+ //
+ // See the comment in FileGenerator::GenerateInlineFunctionDefinitions
+ // for a more complete explanation.
+ if (use_dependent_base_ && IsFieldDependent(field)) {
+ map<string, string> vars;
+ SetCommonFieldVariables(field, &vars, options_);
+ vars["inline"] = "inline ";
+ if (field->containing_oneof()) {
+ vars["field_name"] = UnderscoresToCamelCase(field->name(), true);
+ vars["oneof_name"] = field->containing_oneof()->name();
+ vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index());
+ GenerateOneofMemberHasBits(field, vars, printer);
+ } else if (!field->is_repeated()) {
+ // There will be no header guard, so this always has to be inline.
+ GenerateSingularFieldHasBits(field, vars, printer);
+ }
+ // vars needed for clear_(), which is in the dependent base:
+ // (See also GenerateDependentFieldAccessorDeclarations.)
+ vars["tmpl"] = "template<class T>\n";
+ vars["dependent_classname"] =
+ DependentBaseClassTemplateName(descriptor_) + "<T>";
+ vars["this_message"] = "reinterpret_cast<T*>(this)->";
+ vars["this_const_message"] = "reinterpret_cast<const T*>(this)->";
+ GenerateFieldClear(field, vars, printer);
+ }
+
+ // Generate type-specific accessors.
+ field_generators_.get(field)
+ .GenerateDependentInlineAccessorDefinitions(printer);
+
+ printer->Print("\n");
+ }
+
+ // Generate has_$name$() and clear_has_$name$() functions for oneofs
+ // Similar to other has-bits, these must always be in the header if we
+ // are using a dependent base class.
+ GenerateOneofHasBits(printer, true /* is_inline */);
+}
+
+void MessageGenerator::
+GenerateSingularFieldHasBits(const FieldDescriptor* field,
+ map<string, string> vars,
+ io::Printer* printer) {
+ if (HasFieldPresence(descriptor_->file())) {
+ // N.B.: without field presence, we do not use has-bits or generate
+ // has_$name$() methods.
+ vars["has_array_index"] = SimpleItoa(field->index() / 32);
+ vars["has_mask"] = StrCat(strings::Hex(1u << (field->index() % 32),
+ strings::ZERO_PAD_8));
+ printer->Print(vars,
+ "$inline$"
+ "bool $classname$::has_$name$() const {\n"
+ " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
+ "}\n"
+ "$inline$"
+ "void $classname$::set_has_$name$() {\n"
+ " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n"
+ "}\n"
+ "$inline$"
+ "void $classname$::clear_has_$name$() {\n"
+ " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"
+ "}\n");
+ } else {
+ // Message fields have a has_$name$() method.
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ bool is_lazy = false;
+ if (is_lazy) {
+ printer->Print(vars,
+ "$inline$"
+ "bool $classname$::has_$name$() const {\n"
+ " return !$name$_.IsCleared();\n"
+ "}\n");
+ } else {
+ printer->Print(vars,
+ "$inline$"
+ "bool $classname$::has_$name$() const {\n"
+ " return !_is_default_instance_ && $name$_ != NULL;\n"
+ "}\n");
+ }
+ }
+ }
+}
+
+void MessageGenerator::
+GenerateOneofHasBits(io::Printer* printer, bool is_inline) {
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ map<string, string> vars;
+ vars["oneof_name"] = descriptor_->oneof_decl(i)->name();
+ vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+ vars["cap_oneof_name"] =
+ ToUpper(descriptor_->oneof_decl(i)->name());
+ vars["classname"] = classname_;
+ vars["inline"] = (is_inline ? "inline " : "");
+ printer->Print(
+ vars,
+ "$inline$"
+ "bool $classname$::has_$oneof_name$() const {\n"
+ " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n"
+ "}\n"
+ "$inline$"
+ "void $classname$::clear_has_$oneof_name$() {\n"
+ " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n"
+ "}\n");
+ }
+}
+
+void MessageGenerator::
+GenerateOneofMemberHasBits(const FieldDescriptor* field,
+ const map<string, string>& vars,
+ io::Printer* printer) {
+ // Singular field in a oneof
+ // N.B.: Without field presence, we do not use has-bits or generate
+ // has_$name$() methods, but oneofs still have set_has_$name$().
+ // Oneofs also have has_$name$() but only as a private helper
+ // method, so that generated code is slightly cleaner (vs. comparing
+ // _oneof_case_[index] against a constant everywhere).
+ printer->Print(vars,
+ "$inline$"
+ "bool $classname$::has_$name$() const {\n"
+ " return $oneof_name$_case() == k$field_name$;\n"
+ "}\n");
+ printer->Print(vars,
+ "$inline$"
+ "void $classname$::set_has_$name$() {\n"
+ " _oneof_case_[$oneof_index$] = k$field_name$;\n"
+ "}\n");
+}
+
+void MessageGenerator::
+GenerateFieldClear(const FieldDescriptor* field,
+ const map<string, string>& vars,
+ io::Printer* printer) {
+ // Generate clear_$name$() (See GenerateFieldAccessorDeclarations and
+ // GenerateDependentFieldAccessorDeclarations, $dependent_classname$ is
+ // set by the Generate*Definitions functions.)
+ printer->Print(vars,
+ "$tmpl$"
+ "$inline$"
+ "void $dependent_classname$::clear_$name$() {\n");
+
+ printer->Indent();
+
+ if (field->containing_oneof()) {
+ // Clear this field only if it is the active field in this oneof,
+ // otherwise ignore
+ printer->Print(vars,
+ "if ($this_message$has_$name$()) {\n");
+ printer->Indent();
+ field_generators_.get(field).GenerateClearingCode(printer);
+ printer->Print(vars,
+ "$this_message$clear_has_$oneof_name$();\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ } else {
+ field_generators_.get(field).GenerateClearingCode(printer);
+ if (HasFieldPresence(descriptor_->file())) {
+ if (!field->is_repeated()) {
+ printer->Print(vars,
+ "$this_message$clear_has_$name$();\n");
+ }
+ }
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void MessageGenerator::
+GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) {
printer->Print("// $classname$\n\n", "classname", classname_);
for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -504,122 +751,49 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
map<string, string> vars;
SetCommonFieldVariables(field, &vars, options_);
+ vars["inline"] = is_inline ? "inline " : "";
// Generate has_$name$() or $name$_size().
if (field->is_repeated()) {
printer->Print(vars,
- "inline int $classname$::$name$_size() const {\n"
+ "$inline$"
+ "int $classname$::$name$_size() const {\n"
" return $name$_.size();\n"
"}\n");
} else if (field->containing_oneof()) {
- // Singular field in a oneof
- // N.B.: Without field presence, we do not use has-bits or generate
- // has_$name$() methods, but oneofs still have set_has_$name$().
- // Oneofs also have has_$name$() but only as a private helper
- // method, so that generated code is slightly cleaner (vs. comparing
- // _oneof_case_[index] against a constant everywhere).
vars["field_name"] = UnderscoresToCamelCase(field->name(), true);
vars["oneof_name"] = field->containing_oneof()->name();
vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index());
- printer->Print(vars,
- "inline bool $classname$::has_$name$() const {\n"
- " return $oneof_name$_case() == k$field_name$;\n"
- "}\n");
- printer->Print(vars,
- "inline void $classname$::set_has_$name$() {\n"
- " _oneof_case_[$oneof_index$] = k$field_name$;\n"
- "}\n");
+ if (!use_dependent_base_ || !IsFieldDependent(field)) {
+ GenerateOneofMemberHasBits(field, vars, printer);
+ }
} else {
// Singular field.
- if (HasFieldPresence(descriptor_->file())) {
- // N.B.: without field presence, we do not use has-bits or generate
- // has_$name$() methods.
- char buffer[kFastToBufferSize];
- vars["has_array_index"] = SimpleItoa(field->index() / 32);
- vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32),
- buffer);
- printer->Print(vars,
- "inline bool $classname$::has_$name$() const {\n"
- " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
- "}\n"
- "inline void $classname$::set_has_$name$() {\n"
- " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n"
- "}\n"
- "inline void $classname$::clear_has_$name$() {\n"
- " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"
- "}\n"
- );
- } else {
- // Message fields have a has_$name$() method.
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- bool is_lazy = false;
- if (is_lazy) {
- printer->Print(vars,
- "inline bool $classname$::has_$name$() const {\n"
- " return !$name$_.IsCleared();\n"
- "}\n");
- } else {
- printer->Print(vars,
- "inline bool $classname$::has_$name$() const {\n"
- " return !_is_default_instance_ && $name$_ != NULL;\n"
- "}\n");
- }
- }
+ if (!use_dependent_base_ || !IsFieldDependent(field)) {
+ GenerateSingularFieldHasBits(field, vars, printer);
}
}
- // Generate clear_$name$()
- printer->Print(vars,
- "inline void $classname$::clear_$name$() {\n");
-
- printer->Indent();
-
- if (field->containing_oneof()) {
- // Clear this field only if it is the active field in this oneof,
- // otherwise ignore
- printer->Print(vars,
- "if (has_$name$()) {\n");
- printer->Indent();
- field_generators_.get(field).GenerateClearingCode(printer);
- printer->Print(vars,
- "clear_has_$oneof_name$();\n");
- printer->Outdent();
- printer->Print("}\n");
- } else {
- field_generators_.get(field).GenerateClearingCode(printer);
- if (HasFieldPresence(descriptor_->file())) {
- if (!field->is_repeated()) {
- printer->Print(vars,
- "clear_has_$name$();\n");
- }
- }
+ if (!use_dependent_base_ || !IsFieldDependent(field)) {
+ vars["tmpl"] = "";
+ vars["dependent_classname"] = vars["classname"];
+ vars["this_message"] = "";
+ vars["this_const_message"] = "";
+ GenerateFieldClear(field, vars, printer);
}
- printer->Outdent();
- printer->Print("}\n");
-
// Generate type-specific accessors.
- field_generators_.get(field).GenerateInlineAccessorDefinitions(printer);
+ field_generators_.get(field).GenerateInlineAccessorDefinitions(printer,
+ is_inline);
printer->Print("\n");
}
- // Generate has_$name$() and clear_has_$name$() functions for oneofs
- for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- map<string, string> vars;
- vars["oneof_name"] = descriptor_->oneof_decl(i)->name();
- vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
- vars["cap_oneof_name"] =
- ToUpper(descriptor_->oneof_decl(i)->name());
- vars["classname"] = classname_;
- printer->Print(
- vars,
- "inline bool $classname$::has_$oneof_name$() const {\n"
- " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n"
- "}\n"
- "inline void $classname$::clear_has_$oneof_name$() {\n"
- " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n"
- "}\n");
+ if (!use_dependent_base_) {
+ // Generate has_$name$() and clear_has_$name$() functions for oneofs
+ // If we aren't using a dependent base, they can be with the other functions
+ // that are #ifdef-guarded.
+ GenerateOneofHasBits(printer, is_inline);
}
}
@@ -649,6 +823,34 @@ static bool CanClearByZeroing(const FieldDescriptor* field) {
}
void MessageGenerator::
+GenerateDependentBaseClassDefinition(io::Printer* printer) {
+ if (!use_dependent_base_) {
+ return;
+ }
+
+ map<string, string> vars;
+ vars["classname"] = DependentBaseClassTemplateName(descriptor_);
+ vars["superclass"] = SuperClassName(descriptor_);
+
+ printer->Print(vars,
+ "template <class T>\n"
+ "class $classname$ : public $superclass$ {\n"
+ " public:\n");
+ printer->Indent();
+
+ printer->Print(vars,
+ "$classname$() {}\n"
+ "virtual ~$classname$() {}\n"
+ "\n");
+
+ // Generate dependent accessor methods for all fields.
+ GenerateDependentFieldAccessorDeclarations(printer);
+
+ printer->Outdent();
+ printer->Print("};\n");
+}
+
+void MessageGenerator::
GenerateClassDefinition(io::Printer* printer) {
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// map entry message doesn't need class definition. Since map entry message
@@ -661,6 +863,11 @@ GenerateClassDefinition(io::Printer* printer) {
printer->Print("\n");
}
+ if (use_dependent_base_) {
+ GenerateDependentBaseClassDefinition(printer);
+ printer->Print("\n");
+ }
+
map<string, string> vars;
vars["classname"] = classname_;
vars["field_count"] = SimpleItoa(descriptor_->field_count());
@@ -670,11 +877,18 @@ GenerateClassDefinition(io::Printer* printer) {
} else {
vars["dllexport"] = options_.dllexport_decl + " ";
}
- vars["superclass"] = SuperClassName(descriptor_);
-
+ if (use_dependent_base_) {
+ vars["superclass"] =
+ DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">";
+ } else {
+ vars["superclass"] = SuperClassName(descriptor_);
+ }
printer->Print(vars,
- "class $dllexport$$classname$ : public $superclass$ {\n"
- " public:\n");
+ "class $dllexport$$classname$ : public $superclass$ {\n");
+ if (use_dependent_base_) {
+ printer->Print(vars, " friend class $superclass$;\n");
+ }
+ printer->Print(" public:\n");
printer->Indent();
printer->Print(vars,
@@ -783,6 +997,19 @@ GenerateClassDefinition(io::Printer* printer) {
printer->Print(vars,
"void UnsafeArenaSwap($classname$* other);\n");
}
+
+ if (IsAnyMessage(descriptor_)) {
+ printer->Print(vars,
+ "// implements Any -----------------------------------------------\n"
+ "\n"
+ "void PackFrom(const ::google::protobuf::Message& message);\n"
+ "bool UnpackTo(::google::protobuf::Message* message) const;\n"
+ "template<typename T> bool Is() const {\n"
+ " return _any_metadata_.Is<T>();\n"
+ "}\n"
+ "\n");
+ }
+
printer->Print(vars,
"void Swap($classname$* other);\n"
"\n"
@@ -974,11 +1201,18 @@ GenerateClassDefinition(io::Printer* printer) {
// Generate oneof function declarations
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- printer->Print(
- "inline bool has_$oneof_name$() const;\n"
- "void clear_$oneof_name$();\n"
- "inline void clear_has_$oneof_name$();\n\n",
- "oneof_name", descriptor_->oneof_decl(i)->name());
+ if (use_dependent_base_) {
+ printer->Print(
+ "inline bool has_$oneof_name$() const;\n"
+ "inline void clear_has_$oneof_name$();\n\n",
+ "oneof_name", descriptor_->oneof_decl(i)->name());
+ } else {
+ printer->Print(
+ "inline bool has_$oneof_name$() const;\n"
+ "void clear_$oneof_name$();\n"
+ "inline void clear_has_$oneof_name$();\n\n",
+ "oneof_name", descriptor_->oneof_decl(i)->name());
+ }
}
if (HasGeneratedMethods(descriptor_->file()) &&
@@ -1140,6 +1374,12 @@ GenerateClassDefinition(io::Printer* printer) {
"\n");
}
+ // Generate _any_metadata_ for the Any type.
+ if (IsAnyMessage(descriptor_)) {
+ printer->Print(vars,
+ "::google::protobuf::internal::AnyMetadata _any_metadata_;\n");
+ }
+
// Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as
// friends so that they can access private static variables like
// default_instance_ and reflection_.
@@ -1173,18 +1413,33 @@ GenerateClassDefinition(io::Printer* printer) {
}
void MessageGenerator::
-GenerateInlineMethods(io::Printer* printer) {
+GenerateDependentInlineMethods(io::Printer* printer) {
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // map entry message doesn't need inline methods. Since map entry message
+ // cannot be a top level class, we just need to avoid calling
+ // GenerateInlineMethods here.
+ if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
+ nested_generators_[i]->GenerateDependentInlineMethods(printer);
+ printer->Print(kThinSeparator);
+ printer->Print("\n");
+ }
+
+ GenerateDependentFieldAccessorDefinitions(printer);
+}
+
+void MessageGenerator::
+GenerateInlineMethods(io::Printer* printer, bool is_inline) {
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// map entry message doesn't need inline methods. Since map entry message
// cannot be a top level class, we just need to avoid calling
// GenerateInlineMethods here.
if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
- nested_generators_[i]->GenerateInlineMethods(printer);
+ nested_generators_[i]->GenerateInlineMethods(printer, is_inline);
printer->Print(kThinSeparator);
printer->Print("\n");
}
- GenerateFieldAccessorDefinitions(printer);
+ GenerateFieldAccessorDefinitions(printer, is_inline);
// Generate oneof_case() functions.
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
@@ -1194,9 +1449,11 @@ GenerateInlineMethods(io::Printer* printer) {
descriptor_->oneof_decl(i)->name(), true);
vars["oneof_name"] = descriptor_->oneof_decl(i)->name();
vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+ vars["inline"] = is_inline ? "inline " : "";
printer->Print(
vars,
- "inline $class_name$::$camel_oneof_name$Case $class_name$::"
+ "$inline$"
+ "$class_name$::$camel_oneof_name$Case $class_name$::"
"$oneof_name$_case() const {\n"
" return $class_name$::$camel_oneof_name$Case("
"_oneof_case_[$oneof_index$]);\n"
@@ -1226,7 +1483,9 @@ GenerateDescriptorDeclarations(io::Printer* printer) {
for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
printer->Print(" ");
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
+ (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
+ EffectiveStringCType(field) != FieldOptions::STRING)) {
printer->Print("const ");
}
field_generators_.get(field).GeneratePrivateMembers(printer);
@@ -1395,8 +1654,8 @@ GenerateTypeRegistrations(io::Printer* printer) {
" ::google::protobuf::internal::MapEntry<\n"
" $key$,\n"
" $val$,\n"
- " $key_type$,\n"
- " $val_type$,\n"
+ " $key_wire_type$,\n"
+ " $val_wire_type$,\n"
" $default_enum_value$>::CreateDefaultInstance(\n"
" $classname$_descriptor_));\n");
}
@@ -1492,6 +1751,19 @@ GenerateShutdownCode(io::Printer* printer) {
void MessageGenerator::
GenerateClassMethods(io::Printer* printer) {
+ if (IsAnyMessage(descriptor_)) {
+ printer->Print(
+ "void $classname$::PackFrom(const ::google::protobuf::Message& message) {\n"
+ " _any_metadata_.PackFrom(message);\n"
+ "}\n"
+ "\n"
+ "bool $classname$::UnpackTo(::google::protobuf::Message* message) const {\n"
+ " return _any_metadata_.UnpackTo(message);\n"
+ "}\n"
+ "\n",
+ "classname", classname_);
+ }
+
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
enum_generators_[i]->GenerateMethods(printer);
}
@@ -1765,7 +2037,7 @@ GenerateArenaDestructorCode(io::Printer* printer) {
if (need_registration) {
printer->Print(
"inline void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n"
- " if (arena != NULL) {"
+ " if (arena != NULL) {\n"
" arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n"
" }\n"
"}\n",
@@ -1780,18 +2052,23 @@ GenerateArenaDestructorCode(io::Printer* printer) {
void MessageGenerator::
GenerateStructors(io::Printer* printer) {
- string superclass = SuperClassName(descriptor_);
- string initializer_with_arena;
- if (UseUnknownFieldSet(descriptor_->file())) {
- initializer_with_arena = "_internal_metadata_(arena)";
+ string superclass;
+ if (use_dependent_base_) {
+ superclass =
+ DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">";
} else {
- initializer_with_arena = "_arena_ptr_(arena)";
+ superclass = SuperClassName(descriptor_);
}
+ string initializer_with_arena = superclass + "()";
+
if (descriptor_->extension_range_count() > 0) {
- initializer_with_arena = string("\n _extensions_(arena)") +
- (!initializer_with_arena.empty() ? ", " : "") + initializer_with_arena;
+ initializer_with_arena += ",\n _extensions_(arena)";
+ }
+
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ initializer_with_arena += ",\n _internal_metadata_(arena)";
} else {
- initializer_with_arena = "\n " + initializer_with_arena;
+ initializer_with_arena += ",\n _arena_ptr_(arena)";
}
// Initialize member variables with arena constructor.
@@ -1802,16 +2079,21 @@ GenerateStructors(io::Printer* printer) {
FieldName(descriptor_->field(i)) + string("_(arena)");
}
}
- initializer_with_arena = superclass + "()" +
- (!initializer_with_arena.empty() ? "," : " ") + initializer_with_arena;
+
+ if (IsAnyMessage(descriptor_)) {
+ initializer_with_arena += ",\n _any_metadata_(&type_url, &value_)";
+ }
string initializer_null;
initializer_null = (UseUnknownFieldSet(descriptor_->file()) ?
- ", _internal_metadata_(NULL) " : ", _arena_ptr_(NULL)");
+ ", _internal_metadata_(NULL)" : ", _arena_ptr_(NULL)");
+ if (IsAnyMessage(descriptor_)) {
+ initializer_null += ", _any_metadata_(&type_url_, &value_)";
+ }
printer->Print(
"$classname$::$classname$()\n"
- " : $superclass$() $initializer$ {\n"
+ " : $superclass$()$initializer$ {\n"
" SharedCtor();\n"
" // @@protoc_insertion_point(constructor:$full_name$)\n"
"}\n",
@@ -1892,10 +2174,14 @@ GenerateStructors(io::Printer* printer) {
"full_name", descriptor_->full_name());
if (UseUnknownFieldSet(descriptor_->file())) {
printer->Print(
- ",\n _internal_metadata_(NULL) {\n");
+ ",\n _internal_metadata_(NULL)");
} else if (!UseUnknownFieldSet(descriptor_->file())) {
- printer->Print(",\n _arena_ptr_(NULL) {\n");
+ printer->Print(",\n _arena_ptr_(NULL)");
+ }
+ if (IsAnyMessage(descriptor_)) {
+ printer->Print(",\n _any_metadata_(&type_url_, &value_)");
}
+ printer->Print(" {\n");
printer->Print(
" SharedCtor();\n"
" MergeFrom(from);\n"
@@ -2038,17 +2324,16 @@ GenerateClear(io::Printer* printer) {
// Step 2a: Greedily seek runs of fields that can be cleared by memset-to-0.
// The generated code uses two macros to help it clear runs of fields:
- // OFFSET_OF_FIELD_ computes the offset (in bytes) of a field in the Message.
+ // ZR_HELPER_(f1) - ZR_HELPER_(f0) computes the difference, in bytes, of the
+ // positions of two fields in the Message.
// ZR_ zeroes a non-empty range of fields via memset.
const char* macros =
- "#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \\\n"
- " &reinterpret_cast<$classname$*>(16)->f) - \\\n"
- " reinterpret_cast<char*>(16))\n\n"
- "#define ZR_(first, last) do { \\\n"
- " size_t f = OFFSET_OF_FIELD_(first); \\\n"
- " size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \\\n"
- " ::memset(&first, 0, n); \\\n"
- " } while (0)\n\n";
+ "#define ZR_HELPER_(f) reinterpret_cast<char*>(\\\n"
+ " &reinterpret_cast<$classname$*>(16)->f)\n\n"
+ "#define ZR_(first, last) do {\\\n"
+ " ::memset(&first, 0,\\\n"
+ " ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\\\n"
+ "} while (0)\n\n";
for (int i = 0; i < runs_of_fields_.size(); i++) {
const vector<string>& run = runs_of_fields_[i];
if (run.size() < 2) continue;
@@ -2095,7 +2380,7 @@ GenerateClear(io::Printer* printer) {
} else {
if (HasFieldPresence(descriptor_->file())) {
printer->Print(
- "if (_has_bits_[$index$ / 32] & $mask$) {\n",
+ "if (_has_bits_[$index$ / 32] & $mask$u) {\n",
"index", SimpleItoa(i / 8 * 8),
"mask", SimpleItoa(mask));
printer->Indent();
@@ -2123,7 +2408,11 @@ GenerateClear(io::Printer* printer) {
have_enclosing_if = true;
}
- field_generators_.get(field).GenerateClearingCode(printer);
+ if (use_dependent_base_ && IsFieldDependent(field)) {
+ printer->Print("clear_$name$();\n", "name", fieldname);
+ } else {
+ field_generators_.get(field).GenerateClearingCode(printer);
+ }
if (have_enclosing_if) {
printer->Outdent();
@@ -2137,7 +2426,7 @@ GenerateClear(io::Printer* printer) {
}
if (macros_are_needed) {
printer->Outdent();
- printer->Print("\n#undef OFFSET_OF_FIELD_\n#undef ZR_\n\n");
+ printer->Print("\n#undef ZR_HELPER_\n#undef ZR_\n\n");
printer->Indent();
}
@@ -2146,7 +2435,11 @@ GenerateClear(io::Printer* printer) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->is_repeated()) {
- field_generators_.get(field).GenerateClearingCode(printer);
+ if (use_dependent_base_ && IsFieldDependent(field)) {
+ printer->Print("clear_$name$();\n", "name", FieldName(field));
+ } else {
+ field_generators_.get(field).GenerateClearingCode(printer);
+ }
}
}
@@ -2183,19 +2476,38 @@ void MessageGenerator::
GenerateOneofClear(io::Printer* printer) {
// Generated function clears the active field and union case (e.g. foo_case_).
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- printer->Print(
- "void $classname$::clear_$oneofname$() {\n",
- "classname", classname_,
- "oneofname", descriptor_->oneof_decl(i)->name());
+ map<string, string> oneof_vars;
+ oneof_vars["classname"] = classname_;
+ oneof_vars["oneofname"] = descriptor_->oneof_decl(i)->name();
+ string message_class;
+
+ if (use_dependent_base_) {
+ oneof_vars["tmpl"] = "template<class T>\n";
+ oneof_vars["inline"] = "inline ";
+ oneof_vars["dependent_classname"] =
+ DependentBaseClassTemplateName(descriptor_) + "<T>";
+ oneof_vars["this_message"] = "reinterpret_cast<T*>(this)->";
+ message_class = "T::";
+ } else {
+ oneof_vars["tmpl"] = "";
+ oneof_vars["inline"] = "";
+ oneof_vars["dependent_classname"] = classname_;
+ oneof_vars["this_message"] = "";
+ }
+
+ printer->Print(oneof_vars,
+ "$tmpl$"
+ "$inline$"
+ "void $dependent_classname$::clear_$oneofname$() {\n");
printer->Indent();
- printer->Print(
- "switch($oneofname$_case()) {\n",
- "oneofname", descriptor_->oneof_decl(i)->name());
+ printer->Print(oneof_vars,
+ "switch($this_message$$oneofname$_case()) {\n");
printer->Indent();
for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
printer->Print(
- "case k$field_name$: {\n",
+ "case $message_class$k$field_name$: {\n",
+ "message_class", message_class,
"field_name", UnderscoresToCamelCase(field->name(), true));
printer->Indent();
// We clear only allocated objects in oneofs
@@ -2212,16 +2524,20 @@ GenerateOneofClear(io::Printer* printer) {
"}\n");
}
printer->Print(
- "case $cap_oneof_name$_NOT_SET: {\n"
+ "case $message_class$$cap_oneof_name$_NOT_SET: {\n"
" break;\n"
"}\n",
+ "message_class", message_class,
"cap_oneof_name",
ToUpper(descriptor_->oneof_decl(i)->name()));
printer->Outdent();
printer->Print(
"}\n"
- "_oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n",
+ "$this_message$_oneof_case_[$oneof_index$] = "
+ "$message_class$$cap_oneof_name$_NOT_SET;\n",
+ "this_message", oneof_vars["this_message"],
"oneof_index", SimpleItoa(i),
+ "message_class", message_class,
"cap_oneof_name",
ToUpper(descriptor_->oneof_decl(i)->name()));
printer->Outdent();
@@ -2332,9 +2648,9 @@ GenerateMergeFrom(io::Printer* printer) {
// system, as the GOOGLE_CHECK above ensured that we have the same descriptor
// for each message.
printer->Print(
- "const $classname$* source =\n"
- " ::google::protobuf::internal::dynamic_cast_if_available<const $classname$*>(\n"
- " &from);\n"
+ "const $classname$* source = \n"
+ " ::google::protobuf::internal::DynamicCastToGenerated<const $classname$>(\n"
+ " &from);\n"
"if (source == NULL) {\n"
" ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n"
"} else {\n"
@@ -2584,8 +2900,24 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
printer->Indent();
+ // Find repeated messages and groups now, to simplify what follows.
+ hash_set<int> fields_with_parse_loop;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = ordered_fields[i];
+ if (field->is_repeated() &&
+ (field->type() == FieldDescriptor::TYPE_MESSAGE ||
+ field->type() == FieldDescriptor::TYPE_GROUP)) {
+ fields_with_parse_loop.insert(i);
+ }
+ }
+
+ // need_label is true if we generated "goto parse_$name$" while handling the
+ // previous field.
+ bool need_label = false;
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = ordered_fields[i];
+ const bool loops = fields_with_parse_loop.count(i) > 0;
+ const bool next_field_loops = fields_with_parse_loop.count(i + 1) > 0;
PrintFieldComment(printer, field);
@@ -2599,14 +2931,21 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
printer->Print("if (tag == $commontag$) {\n",
"commontag", SimpleItoa(WireFormat::MakeTag(field)));
- if (i > 0 || (field->is_repeated() && !field->options().packed())) {
+ if (need_label ||
+ (field->is_repeated() && !field->is_packed() && !loops)) {
printer->Print(
- " parse_$name$:\n",
+ " parse_$name$:\n",
+ "name", field->name());
+ }
+ if (loops) {
+ printer->Print(
+ " DO_(input->IncrementRecursionDepth());\n"
+ " parse_loop_$name$:\n",
"name", field->name());
}
printer->Indent();
- if (field->options().packed()) {
+ if (field->is_packed()) {
field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
} else {
field_generator.GenerateMergeFromCodedStream(printer);
@@ -2614,7 +2953,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
printer->Outdent();
// Emit code to parse unexpectedly packed or unpacked values.
- if (field->is_packable() && field->options().packed()) {
+ if (field->is_packed()) {
internal::WireFormatLite::WireType wiretype =
WireFormat::WireTypeForFieldType(field->type());
printer->Print("} else if (tag == $uncommontag$) {\n",
@@ -2624,7 +2963,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
printer->Indent();
field_generator.GenerateMergeFromCodedStream(printer);
printer->Outdent();
- } else if (field->is_packable() && !field->options().packed()) {
+ } else if (field->is_packable() && !field->is_packed()) {
internal::WireFormatLite::WireType wiretype =
internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
printer->Print("} else if (tag == $uncommontag$) {\n",
@@ -2643,26 +2982,53 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
// switch() is slow since it can't be predicted well. Insert some if()s
// here that attempt to predict the next tag.
- if (field->is_repeated() && !field->options().packed()) {
- // Expect repeats of this field.
+ // For non-packed repeated fields, expect the same tag again.
+ if (loops) {
+ printer->Print(
+ "if (input->ExpectTag($tag$)) goto parse_loop_$name$;\n",
+ "tag", SimpleItoa(WireFormat::MakeTag(field)),
+ "name", field->name());
+ } else if (field->is_repeated() && !field->is_packed()) {
printer->Print(
"if (input->ExpectTag($tag$)) goto parse_$name$;\n",
"tag", SimpleItoa(WireFormat::MakeTag(field)),
"name", field->name());
}
- if (i + 1 < descriptor_->field_count()) {
- // Expect the next field in order.
- const FieldDescriptor* next_field = ordered_fields[i + 1];
- printer->Print(
- "if (input->ExpectTag($next_tag$)) goto parse_$next_name$;\n",
- "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)),
- "next_name", next_field->name());
- } else {
- // Expect EOF.
- // TODO(kenton): Expect group end-tag?
+ // Have we emitted "if (input->ExpectTag($next_tag$)) ..." yet?
+ bool emitted_goto_next_tag = false;
+
+ // For repeated messages/groups, we need to decrement recursion depth,
+ // unless the next tag is also for a repeated message/group.
+ if (loops) {
+ if (next_field_loops) {
+ const FieldDescriptor* next_field = ordered_fields[i + 1];
+ printer->Print(
+ "if (input->ExpectTag($next_tag$)) goto parse_loop_$next_name$;\n",
+ "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)),
+ "next_name", next_field->name());
+ emitted_goto_next_tag = true;
+ }
printer->Print(
- "if (input->ExpectAtEnd()) goto success;\n");
+ "input->UnsafeDecrementRecursionDepth();\n");
+ }
+
+ // If there are more fields, expect the next one.
+ need_label = false;
+ if (!emitted_goto_next_tag) {
+ if (i + 1 == descriptor_->field_count()) {
+ // Expect EOF.
+ // TODO(kenton): Expect group end-tag?
+ printer->Print(
+ "if (input->ExpectAtEnd()) goto success;\n");
+ } else {
+ const FieldDescriptor* next_field = ordered_fields[i + 1];
+ printer->Print(
+ "if (input->ExpectTag($next_tag$)) goto parse_$next_name$;\n",
+ "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)),
+ "next_name", next_field->name());
+ need_label = true;
+ }
}
printer->Print(
@@ -2923,8 +3289,8 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
sorted_extensions.push_back(descriptor_->extension_range(i));
}
- sort(sorted_extensions.begin(), sorted_extensions.end(),
- ExtensionRangeSorter());
+ std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+ ExtensionRangeSorter());
// Merge the fields and the extension ranges, both sorted by field number.
int i, j;
@@ -2998,9 +3364,7 @@ static string ConditionalToCheckBitmasks(const vector<uint32>& masks) {
vector<string> parts;
for (int i = 0; i < masks.size(); i++) {
if (masks[i] == 0) continue;
- char buffer[kFastToBufferSize];
- FastHex32ToBuffer(masks[i], buffer);
- string m = StrCat("0x", buffer);
+ string m = StrCat("0x", strings::Hex(masks[i], strings::ZERO_PAD_8));
// Each xor evaluates to 0 if the expected bits are present.
parts.push_back(StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")"));
}
@@ -3146,7 +3510,7 @@ GenerateByteSize(io::Printer* printer) {
} else {
if (HasFieldPresence(descriptor_->file())) {
printer->Print(
- "if (_has_bits_[$index$ / 32] & $mask$) {\n",
+ "if (_has_bits_[$index$ / 32] & $mask$u) {\n",
"index", SimpleItoa(i),
"mask", SimpleItoa(mask));
printer->Indent();
@@ -3292,11 +3656,10 @@ GenerateIsInitialized(io::Printer* printer) {
}
if (mask != 0) {
- char buffer[kFastToBufferSize];
printer->Print(
"if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n",
"i", SimpleItoa(i),
- "mask", FastHex32ToBuffer(mask, buffer));
+ "mask", StrCat(strings::Hex(mask, strings::ZERO_PAD_8)));
}
}
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index dfbc9af5..23dad10c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -67,7 +67,8 @@ class MessageGenerator {
// Header stuff.
// Generate foward declarations for this class and all its nested types.
- void GenerateForwardDeclaration(io::Printer* printer);
+ void GenerateMessageForwardDeclaration(io::Printer* printer);
+ void GenerateEnumForwardDeclaration(io::Printer* printer);
// Generate definitions of all nested enums (must come before class
// definitions because those classes use the enums definitions).
@@ -82,7 +83,10 @@ class MessageGenerator {
// Generate definitions of inline methods (placed at the end of the header
// file).
- void GenerateInlineMethods(io::Printer* printer);
+ void GenerateInlineMethods(io::Printer* printer, bool is_inline);
+
+ // Dependent methods are always inline.
+ void GenerateDependentInlineMethods(io::Printer* printer);
// Source file stuff.
@@ -115,8 +119,11 @@ class MessageGenerator {
private:
// Generate declarations and definitions of accessors for fields.
+ void GenerateDependentBaseClassDefinition(io::Printer* printer);
+ void GenerateDependentFieldAccessorDeclarations(io::Printer* printer);
void GenerateFieldAccessorDeclarations(io::Printer* printer);
- void GenerateFieldAccessorDefinitions(io::Printer* printer);
+ void GenerateDependentFieldAccessorDefinitions(io::Printer* printer);
+ void GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline);
// Generate the field offsets array.
void GenerateOffsets(io::Printer* printer);
@@ -158,6 +165,21 @@ class MessageGenerator {
bool unbounded);
+ // Generates has_foo() functions and variables for singular field has-bits.
+ void GenerateSingularFieldHasBits(const FieldDescriptor* field,
+ map<string, string> vars,
+ io::Printer* printer);
+ // Generates has_foo() functions and variables for oneof field has-bits.
+ void GenerateOneofHasBits(io::Printer* printer, bool is_inline);
+ // Generates has_foo_bar() functions for oneof members.
+ void GenerateOneofMemberHasBits(const FieldDescriptor* field,
+ const map<string, string>& vars,
+ io::Printer* printer);
+ // Generates the clear_foo() method for a field.
+ void GenerateFieldClear(const FieldDescriptor* field,
+ const map<string, string>& vars,
+ io::Printer* printer);
+
const Descriptor* descriptor_;
string classname_;
Options options_;
@@ -168,6 +190,7 @@ class MessageGenerator {
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
int num_required_fields_;
bool uses_string_;
+ bool use_dependent_base_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
};
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index b3cd0ba1..ba318d10 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -72,7 +72,8 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
MessageFieldGenerator::
MessageFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
- : descriptor_(descriptor) {
+ : descriptor_(descriptor),
+ dependent_field_(options.proto_h && IsFieldDependent(descriptor)) {
SetMessageVariables(descriptor, &variables_, options);
}
@@ -84,77 +85,152 @@ GeneratePrivateMembers(io::Printer* printer) const {
}
void MessageFieldGenerator::
+GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+}
+
+void MessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "private:\n"
+ "void _slow_mutable_$name$()$deprecation$;\n");
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables_,
+ "void _slow_set_allocated_$name$(\n"
+ " ::google::protobuf::Arena* message_arena, $type$** $name$)$deprecation$;\n");
+ }
+ printer->Print(variables_,
+ "$type$* _slow_$release_name$()$deprecation$;\n"
+ "public:\n");
+ }
printer->Print(variables_,
- "inline const $type$& $name$() const$deprecation$;\n"
- "inline $type$* mutable_$name$()$deprecation$;\n"
- "inline $type$* $release_name$()$deprecation$;\n"
- "inline void set_allocated_$name$($type$* $name$)$deprecation$;\n");
+ "const $type$& $name$() const$deprecation$;\n"
+ "$type$* mutable_$name$()$deprecation$;\n"
+ "$type$* $release_name$()$deprecation$;\n"
+ "void set_allocated_$name$($type$* $name$)$deprecation$;\n");
if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
- "inline $type$* unsafe_arena_release_$name$()$deprecation$;\n"
- "inline void unsafe_arena_set_allocated_$name$(\n"
+ "$type$* unsafe_arena_release_$name$()$deprecation$;\n"
+ "void unsafe_arena_set_allocated_$name$(\n"
" $type$* $name$)$deprecation$;\n");
}
}
+void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "void $classname$::_slow_mutable_$name$() {\n");
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables_,
+ " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
+ } else {
+ printer->Print(variables_,
+ " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
+ }
+ printer->Print(variables_,
+ "}\n"
+ "$type$* $classname$::_slow_$release_name$() {\n"
+ " if ($name$_ == NULL) {\n"
+ " return NULL;\n"
+ " } else {\n"
+ " $type$* temp = new $type$;\n"
+ " temp->MergeFrom(*$name$_);\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ " }\n"
+ "}\n"
+ "$type$* $classname$::unsafe_arena_release_$name$() {\n"
+ " $clear_hasbit$\n"
+ " $type$* temp = $name$_;\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ "}\n");
+ if (SupportsArenas(descriptor_->message_type())) {
+ // NOTE: the same logic is mirrored in weak_message_field.cc. Any
+ // arena-related semantics changes should be made in both places.
+ printer->Print(variables_,
+ "void $classname$::_slow_set_allocated_$name$(\n"
+ " ::google::protobuf::Arena* message_arena, $type$** $name$) {\n"
+ " if (message_arena != NULL && \n"
+ " ::google::protobuf::Arena::GetArena(*$name$) == NULL) {\n"
+ " message_arena->Own(*$name$);\n"
+ " } else if (message_arena !=\n"
+ " ::google::protobuf::Arena::GetArena(*$name$)) {\n"
+ " $type$* new_$name$ = \n"
+ " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+ " message_arena);\n"
+ " new_$name$->CopyFrom(**$name$);\n"
+ " *$name$ = new_$name$;\n"
+ " }\n"
+ "}\n");
+ }
+ printer->Print(variables_,
+ "void $classname$::unsafe_arena_set_allocated_$name$(\n"
+ " $type$* $name$) {\n"
+ // If we're not on an arena, free whatever we were holding before.
+ // (If we are on arena, we can just forget the earlier pointer.)
+ " if (GetArenaNoVirtual() == NULL) {\n"
+ " delete $name$_;\n"
+ " }\n"
+ " $name$_ = $name$;\n"
+ " if ($name$) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
+ ":$full_name$)\n"
+ "}\n");
+ }
+}
+
void MessageFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline const $type$& $classname$::$name$() const {\n"
+GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+}
+
+void MessageFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ const $type$& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n");
PrintHandlingOptionalStaticInitializers(
- variables_, descriptor_->file(), printer,
+ variables, descriptor_->file(), printer,
// With static initializers.
" return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
// Without.
" return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
+ printer->Print(variables,
"}\n"
- "inline $type$* $classname$::mutable_$name$() {\n"
+ "$inline$ $type$* $classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
- " if ($name$_ == NULL) {\n");
- if (SupportsArenas(descriptor_->message_type())) {
- printer->Print(variables_,
- " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
- " GetArenaNoVirtual());\n");
- } else {
- printer->Print(variables_,
- " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
- " GetArenaNoVirtual());\n");
- }
- printer->Print(variables_, " }\n"
+ " if ($name$_ == NULL) {\n"
+ " _slow_mutable_$name$();"
+ " }\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "inline $type$* $classname$::$release_name$() {\n"
+ "$inline$ $type$* $classname$::$release_name$() {\n"
" $clear_hasbit$\n"
" if (GetArenaNoVirtual() != NULL) {\n"
- " if ($name$_ == NULL) {\n"
- " return NULL;\n"
- " } else {\n"
- " $type$* temp = new $type$;\n"
- " temp->MergeFrom(*$name$_);\n"
- " $name$_ = NULL;\n"
- " return temp;\n"
- " }\n"
+ " return _slow_$release_name$();\n"
" } else {\n"
" $type$* temp = $name$_;\n"
" $name$_ = NULL;\n"
" return temp;\n"
" }\n"
"}\n"
- "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
- " $clear_hasbit$\n"
- " $type$* temp = $name$_;\n"
- " $name$_ = NULL;\n"
- " return temp;\n"
- "}\n"
- "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
- " if (GetArenaNoVirtual() == NULL) {\n"
+ "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ " ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n"
+ " if (message_arena == NULL) {\n"
" delete $name$_;\n"
" }\n"
" if ($name$ != NULL) {\n");
@@ -164,26 +240,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
// so we might as well defer it. Otherwise, if incoming message is on a
// different ownership domain (specific arena, or the heap) than we are,
// copy to our arena (or heap, as the case may be).
- printer->Print(variables_,
- " if (GetArenaNoVirtual() != NULL && \n"
- " ::google::protobuf::Arena::GetArena($name$) == NULL) {\n"
- " GetArenaNoVirtual()->Own($name$);\n"
- " } else if (GetArenaNoVirtual() !=\n"
- " ::google::protobuf::Arena::GetArena($name$)) {\n"
- " $type$* new_$name$ = \n"
- " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
- " GetArenaNoVirtual());\n"
- " new_$name$->CopyFrom(*$name$);\n"
- " $name$ = new_$name$;\n"
- " }\n");
+ printer->Print(variables,
+ " _slow_set_allocated_$name$(message_arena, &$name$);\n");
} else {
- printer->Print(variables_,
- " if (GetArenaNoVirtual() != NULL) {\n"
- " GetArenaNoVirtual()->Own($name$);\n"
+ printer->Print(variables,
+ " if (message_arena != NULL) {\n"
+ " message_arena->Own($name$);\n"
" }\n");
}
-
- printer->Print(variables_,
+ printer->Print(variables,
" }\n"
" $name$_ = $name$;\n"
" if ($name$) {\n"
@@ -192,27 +257,11 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $clear_hasbit$\n"
" }\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
- "}\n"
- "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
- " $type$* $name$) {\n"
- // If we're not on an arena, free whatever we were holding before.
- // (If we are on arena, we can just forget the earlier pointer.)
- " if (GetArenaNoVirtual() == NULL) {\n"
- " delete $name$_;\n"
- " }\n"
- " $name$_ = $name$;\n"
- " if ($name$) {\n"
- " $set_hasbit$\n"
- " } else {\n"
- " $clear_hasbit$\n"
- " }\n"
- " // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
- ":$full_name$)\n"
"}\n");
} else {
- printer->Print(variables_,
+ printer->Print(variables,
"}\n"
- "inline $type$* $classname$::mutable_$name$() {\n"
+ "$inline$ $type$* $classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
" if ($name$_ == NULL) {\n"
" $name$_ = new $type$;\n"
@@ -220,17 +269,17 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "inline $type$* $classname$::$release_name$() {\n"
+ "$inline$ $type$* $classname$::$release_name$() {\n"
" $clear_hasbit$\n"
" $type$* temp = $name$_;\n"
" $name$_ = NULL;\n"
" return temp;\n"
"}\n"
- "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
" delete $name$_;\n");
if (SupportsArenas(descriptor_->message_type())) {
- printer->Print(variables_,
+ printer->Print(variables,
" if ($name$ != NULL && $name$->GetArena() != NULL) {\n"
" $type$* new_$name$ = new $type$;\n"
" new_$name$->CopyFrom(*$name$);\n"
@@ -238,7 +287,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" }\n");
}
- printer->Print(variables_,
+ printer->Print(variables,
" $name$_ = $name$;\n"
" if ($name$) {\n"
" $set_hasbit$\n"
@@ -256,7 +305,7 @@ GenerateClearingCode(io::Printer* printer) const {
// If we don't have has-bits, message presence is indicated only by ptr !=
// NULL. Thus on clear, we need to delete the object.
printer->Print(variables_,
- "if ($name$_ != NULL) delete $name$_;\n"
+ "if (GetArenaNoVirtual() == NULL && $name$_ != NULL) delete $name$_;\n"
"$name$_ = NULL;\n");
} else {
printer->Print(variables_,
@@ -328,35 +377,42 @@ MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
void MessageOneofFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+}
+
+void MessageOneofFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
- "inline const $type$& $classname$::$name$() const {\n"
+ printer->Print(variables,
+ "$inline$ const $type$& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return has_$name$() ? *$oneof_prefix$$name$_\n"
" : $type$::default_instance();\n"
"}\n"
- "inline $type$* $classname$::mutable_$name$() {\n"
+ "$inline$ $type$* $classname$::mutable_$name$() {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n");
if (SupportsArenas(descriptor_->message_type())) {
- printer->Print(variables_,
+ printer->Print(variables,
" $oneof_prefix$$name$_ = \n"
" ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
" GetArenaNoVirtual());\n");
} else {
- printer->Print(variables_,
+ printer->Print(variables,
" $oneof_prefix$$name$_ = \n"
" ::google::protobuf::Arena::Create< $type$ >(\n"
" GetArenaNoVirtual());\n");
}
- printer->Print(variables_,
+ printer->Print(variables,
" }\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $oneof_prefix$$name$_;\n"
"}\n"
- "inline $type$* $classname$::$release_name$() {\n"
+ "$inline$ $type$* $classname$::$release_name$() {\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" if (GetArenaNoVirtual() != NULL) {\n"
@@ -375,7 +431,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" return NULL;\n"
" }\n"
"}\n"
- "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
+ "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" $type$* temp = $oneof_prefix$$name$_;\n"
@@ -385,12 +441,12 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" return NULL;\n"
" }\n"
"}\n"
- "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
" clear_$oneof_name$();\n"
" if ($name$) {\n");
if (SupportsArenas(descriptor_->message_type())) {
- printer->Print(variables_,
+ printer->Print(variables,
// If incoming message is on the heap and we are on an arena, just Own()
// it (see above). If it's on a different arena than we are or one of us
// is on the heap, we make a copy to our arena/heap.
@@ -406,19 +462,19 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $name$ = new_$name$;\n"
" }\n");
} else {
- printer->Print(variables_,
+ printer->Print(variables,
" if (GetArenaNoVirtual() != NULL) {\n"
" GetArenaNoVirtual()->Own($name$);\n"
" }\n");
}
- printer->Print(variables_,
+ printer->Print(variables,
" set_has_$name$();\n"
" $oneof_prefix$$name$_ = $name$;\n"
" }\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n"
- "inline void $classname$::unsafe_arena_set_allocated_$name$("
+ "$inline$ void $classname$::unsafe_arena_set_allocated_$name$("
"$type$* $name$) {\n"
// We rely on the oneof clear method to free the earlier contents of this
// oneof. We can directly use the pointer we're given to set the new
@@ -432,13 +488,13 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"$full_name$)\n"
"}\n");
} else {
- printer->Print(variables_,
- "inline const $type$& $classname$::$name$() const {\n"
+ printer->Print(variables,
+ "$inline$ const $type$& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return has_$name$() ? *$oneof_prefix$$name$_\n"
" : $type$::default_instance();\n"
"}\n"
- "inline $type$* $classname$::mutable_$name$() {\n"
+ "$inline$ $type$* $classname$::mutable_$name$() {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -447,7 +503,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $oneof_prefix$$name$_;\n"
"}\n"
- "inline $type$* $classname$::$release_name$() {\n"
+ "$inline$ $type$* $classname$::$release_name$() {\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" $type$* temp = $oneof_prefix$$name$_;\n"
@@ -457,18 +513,18 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" return NULL;\n"
" }\n"
"}\n"
- "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
" clear_$oneof_name$();\n"
" if ($name$) {\n");
if (SupportsArenas(descriptor_->message_type())) {
- printer->Print(variables_,
+ printer->Print(variables,
" if ($name$->GetArena() != NULL) {\n"
" $type$* new_$name$ = new $type$;\n"
" new_$name$->CopyFrom(*$name$);\n"
" $name$ = new_$name$;\n"
" }\n");
}
- printer->Print(variables_,
+ printer->Print(variables,
" set_has_$name$();\n"
" $oneof_prefix$$name$_ = $name$;\n"
" }\n"
@@ -519,40 +575,51 @@ GeneratePrivateMembers(io::Printer* printer) const {
}
void RepeatedMessageFieldGenerator::
+GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+}
+
+void RepeatedMessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "inline const $type$& $name$(int index) const$deprecation$;\n"
- "inline $type$* mutable_$name$(int index)$deprecation$;\n"
- "inline $type$* add_$name$()$deprecation$;\n");
+ "const $type$& $name$(int index) const$deprecation$;\n"
+ "$type$* mutable_$name$(int index)$deprecation$;\n"
+ "$type$* add_$name$()$deprecation$;\n");
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
" $name$() const$deprecation$;\n"
- "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
+ "::google::protobuf::RepeatedPtrField< $type$ >*\n"
" mutable_$name$()$deprecation$;\n");
}
void RepeatedMessageFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline const $type$& $classname$::$name$(int index) const {\n"
+GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ const $type$& $classname$::$name$(int index) const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.$cppget$(index);\n"
"}\n"
- "inline $type$* $classname$::mutable_$name$(int index) {\n"
+ "$inline$ $type$* $classname$::mutable_$name$(int index) {\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_.Mutable(index);\n"
"}\n"
- "inline $type$* $classname$::add_$name$() {\n"
+ "$inline$ $type$* $classname$::add_$name$() {\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
" return $name$_.Add();\n"
"}\n");
- printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ printer->Print(variables,
+ "$inline$ const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
+ "$inline$ ::google::protobuf::RepeatedPtrField< $type$ >*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$name$_;\n"
@@ -583,11 +650,13 @@ void RepeatedMessageFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
printer->Print(variables_,
- "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
+ "DO_(::google::protobuf::internal::WireFormatLite::"
+ "ReadMessageNoVirtualNoRecursionDepth(\n"
" input, add_$name$()));\n");
} else {
printer->Print(variables_,
- "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
+ "DO_(::google::protobuf::internal::WireFormatLite::"
+ "ReadGroupNoVirtualNoRecursionDepth(\n"
" $number$, input, add_$name$()));\n");
}
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h
index 2dff3144..9ddf9643 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -52,8 +52,12 @@ class MessageFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
+ void GenerateDependentAccessorDeclarations(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
+ void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
@@ -65,6 +69,7 @@ class MessageFieldGenerator : public FieldGenerator {
protected:
const FieldDescriptor* descriptor_;
+ const bool dependent_field_;
map<string, string> variables_;
private:
@@ -78,7 +83,10 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator {
~MessageOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
+ void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {}
void GenerateClearingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
@@ -95,8 +103,11 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
+ void GenerateDependentAccessorDeclarations(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h
index 0c99cff1..4463f200 100644
--- a/src/google/protobuf/compiler/cpp/cpp_options.h
+++ b/src/google/protobuf/compiler/cpp/cpp_options.h
@@ -41,12 +41,13 @@ namespace protobuf {
namespace compiler {
namespace cpp {
-// Generator options:
+// Generator options (see generator.cc for a description of each):
struct Options {
- Options() : safe_boundary_check(false) {
+ Options() : safe_boundary_check(false), proto_h(false) {
}
string dllexport_decl;
bool safe_boundary_check;
+ bool proto_h;
};
} // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 9a2c930e..9f929d37 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -117,18 +117,20 @@ GeneratePrivateMembers(io::Printer* printer) const {
void PrimitiveFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "inline $type$ $name$() const$deprecation$;\n"
- "inline void set_$name$($type$ value)$deprecation$;\n");
+ "$type$ $name$() const$deprecation$;\n"
+ "void set_$name$($type$ value)$deprecation$;\n");
}
void PrimitiveFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline $type$ $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ $type$ $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "inline void $classname$::set_$name$($type$ value) {\n"
+ "$inline$ void $classname$::set_$name$($type$ value) {\n"
" $set_hasbit$\n"
" $name$_ = value;\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
@@ -204,16 +206,18 @@ PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
void PrimitiveOneofFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline $type$ $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ $type$ $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" if (has_$name$()) {\n"
" return $oneof_prefix$$name$_;\n"
" }\n"
" return $default$;\n"
"}\n"
- "inline void $classname$::set_$name$($type$ value) {\n"
+ "$inline$ void $classname$::set_$name$($type$ value) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -258,7 +262,7 @@ RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
: descriptor_(descriptor) {
SetPrimitiveVariables(descriptor, &variables_, options);
- if (descriptor->options().packed()) {
+ if (descriptor->is_packed()) {
variables_["packed_reader"] = "ReadPackedPrimitive";
variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
} else {
@@ -273,7 +277,7 @@ void RepeatedPrimitiveFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_,
"::google::protobuf::RepeatedField< $type$ > $name$_;\n");
- if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) {
+ if (descriptor_->is_packed() && HasGeneratedMethods(descriptor_->file())) {
printer->Print(variables_,
"mutable int _$name$_cached_byte_size_;\n");
}
@@ -282,38 +286,40 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "inline $type$ $name$(int index) const$deprecation$;\n"
- "inline void set_$name$(int index, $type$ value)$deprecation$;\n"
- "inline void add_$name$($type$ value)$deprecation$;\n");
+ "$type$ $name$(int index) const$deprecation$;\n"
+ "void set_$name$(int index, $type$ value)$deprecation$;\n"
+ "void add_$name$($type$ value)$deprecation$;\n");
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
+ "const ::google::protobuf::RepeatedField< $type$ >&\n"
" $name$() const$deprecation$;\n"
- "inline ::google::protobuf::RepeatedField< $type$ >*\n"
+ "::google::protobuf::RepeatedField< $type$ >*\n"
" mutable_$name$()$deprecation$;\n");
}
void RepeatedPrimitiveFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline $type$ $classname$::$name$(int index) const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ $type$ $classname$::$name$(int index) const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.Get(index);\n"
"}\n"
- "inline void $classname$::set_$name$(int index, $type$ value) {\n"
+ "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n"
" $name$_.Set(index, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "inline void $classname$::add_$name$($type$ value) {\n"
+ "$inline$ void $classname$::add_$name$($type$ value) {\n"
" $name$_.Add(value);\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n");
- printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
+ printer->Print(variables,
+ "$inline$ const ::google::protobuf::RepeatedField< $type$ >&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "inline ::google::protobuf::RepeatedField< $type$ >*\n"
+ "$inline$ ::google::protobuf::RepeatedField< $type$ >*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$name$_;\n"
@@ -358,7 +364,7 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
// Write the tag and the size.
printer->Print(variables_,
"if (this->$name$_size() > 0) {\n"
@@ -371,7 +377,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
}
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n"
" this->$name$(i), output);\n");
@@ -385,7 +391,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
// Write the tag and the size.
printer->Print(variables_,
"if (this->$name$_size() > 0) {\n"
@@ -399,7 +405,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
}
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
" target = ::google::protobuf::internal::WireFormatLite::\n"
" Write$declared_type$NoTagToArray(this->$name$(i), target);\n");
@@ -429,7 +435,7 @@ GenerateByteSize(io::Printer* printer) const {
"data_size = $fixed_size$ * this->$name$_size();\n");
}
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
"if (data_size > 0) {\n"
" total_size += $tag_size$ +\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
index 97b5e867..fcd7d684 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -53,7 +53,8 @@ class PrimitiveFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
@@ -78,7 +79,8 @@ class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
~PrimitiveOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
@@ -97,7 +99,8 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_service.cc b/src/google/protobuf/compiler/cpp/cpp_service.cc
index a8f303da..226c2aa0 100644
--- a/src/google/protobuf/compiler/cpp/cpp_service.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_service.cc
@@ -301,7 +301,7 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
printer->Print(vars_,
" default:\n"
" GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
- " return *reinterpret_cast< ::google::protobuf::Message*>(NULL);\n"
+ " return *static_cast< ::google::protobuf::Message*>(NULL);\n"
" }\n"
"}\n"
"\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 04ed08c9..1a3896a1 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -127,7 +127,11 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
// files that applied the ctype. The field can still be accessed via the
// reflection interface since the reflection interface is independent of
// the string's underlying representation.
- if (descriptor_->options().ctype() != FieldOptions::STRING) {
+
+ bool unknown_ctype =
+ descriptor_->options().ctype() != EffectiveStringCType(descriptor_);
+
+ if (unknown_ctype) {
printer->Outdent();
printer->Print(
" private:\n"
@@ -136,23 +140,23 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
}
printer->Print(variables_,
- "inline const ::std::string& $name$() const$deprecation$;\n"
- "inline void set_$name$(const ::std::string& value)$deprecation$;\n"
- "inline void set_$name$(const char* value)$deprecation$;\n"
- "inline void set_$name$(const $pointer_type$* value, size_t size)"
+ "const ::std::string& $name$() const$deprecation$;\n"
+ "void set_$name$(const ::std::string& value)$deprecation$;\n"
+ "void set_$name$(const char* value)$deprecation$;\n"
+ "void set_$name$(const $pointer_type$* value, size_t size)"
"$deprecation$;\n"
- "inline ::std::string* mutable_$name$()$deprecation$;\n"
- "inline ::std::string* $release_name$()$deprecation$;\n"
- "inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
+ "::std::string* mutable_$name$()$deprecation$;\n"
+ "::std::string* $release_name$()$deprecation$;\n"
+ "void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
- "inline ::std::string* unsafe_arena_release_$name$()$deprecation$;\n"
- "inline void unsafe_arena_set_allocated_$name$(\n"
+ "::std::string* unsafe_arena_release_$name$()$deprecation$;\n"
+ "void unsafe_arena_set_allocated_$name$(\n"
" ::std::string* $name$)$deprecation$;\n");
}
- if (descriptor_->options().ctype() != FieldOptions::STRING) {
+ if (unknown_ctype) {
printer->Outdent();
printer->Print(" public:\n");
printer->Indent();
@@ -160,25 +164,28 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
}
void StringFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
- "inline const ::std::string& $classname$::$name$() const {\n"
+ printer->Print(variables,
+ "$inline$ const ::std::string& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.Get($default_variable$);\n"
"}\n"
- "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+ "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
" $set_hasbit$\n"
" $name$_.Set($default_variable$, value, GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "inline void $classname$::set_$name$(const char* value) {\n"
+ "$inline$ void $classname$::set_$name$(const char* value) {\n"
" $set_hasbit$\n"
" $name$_.Set($default_variable$, $string_piece$(value),\n"
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
- "inline "
+ "$inline$ "
"void $classname$::set_$name$(const $pointer_type$* value,\n"
" size_t size) {\n"
" $set_hasbit$\n"
@@ -186,22 +193,22 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
- "inline ::std::string* $classname$::mutable_$name$() {\n"
+ "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_.Mutable($default_variable$, GetArenaNoVirtual());\n"
"}\n"
- "inline ::std::string* $classname$::$release_name$() {\n"
+ "$inline$ ::std::string* $classname$::$release_name$() {\n"
" $clear_hasbit$\n"
" return $name$_.Release($default_variable$, GetArenaNoVirtual());\n"
"}\n"
- "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+ "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
" $clear_hasbit$\n"
" return $name$_.UnsafeArenaRelease($default_variable$,\n"
" GetArenaNoVirtual());\n"
"}\n"
- "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
" if ($name$ != NULL) {\n"
" $set_hasbit$\n"
" } else {\n"
@@ -211,7 +218,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n"
- "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
+ "$inline$ void $classname$::unsafe_arena_set_allocated_$name$(\n"
" ::std::string* $name$) {\n"
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
" if ($name$ != NULL) {\n"
@@ -219,29 +226,28 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" } else {\n"
" $clear_hasbit$\n"
" }\n"
- " $set_hasbit$\n"
" $name$_.UnsafeArenaSetAllocated($default_variable$,\n"
" $name$, GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n");
} else {
// No-arena case.
- printer->Print(variables_,
- "inline const ::std::string& $classname$::$name$() const {\n"
+ printer->Print(variables,
+ "$inline$ const ::std::string& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.GetNoArena($default_variable$);\n"
"}\n"
- "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+ "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
" $set_hasbit$\n"
" $name$_.SetNoArena($default_variable$, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "inline void $classname$::set_$name$(const char* value) {\n"
+ "$inline$ void $classname$::set_$name$(const char* value) {\n"
" $set_hasbit$\n"
" $name$_.SetNoArena($default_variable$, $string_piece$(value));\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
- "inline "
+ "$inline$ "
"void $classname$::set_$name$(const $pointer_type$* value, "
"size_t size) {\n"
" $set_hasbit$\n"
@@ -249,16 +255,16 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $string_piece$(reinterpret_cast<const char*>(value), size));\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
- "inline ::std::string* $classname$::mutable_$name$() {\n"
+ "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_.MutableNoArena($default_variable$);\n"
"}\n"
- "inline ::std::string* $classname$::$release_name$() {\n"
+ "$inline$ ::std::string* $classname$::$release_name$() {\n"
" $clear_hasbit$\n"
" return $name$_.ReleaseNoArena($default_variable$);\n"
"}\n"
- "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
" if ($name$ != NULL) {\n"
" $set_hasbit$\n"
" } else {\n"
@@ -422,17 +428,20 @@ StringOneofFieldGenerator(const FieldDescriptor* descriptor,
StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
void StringOneofFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
- "inline const ::std::string& $classname$::$name$() const {\n"
+ printer->Print(variables,
+ "$inline$ const ::std::string& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" if (has_$name$()) {\n"
" return $oneof_prefix$$name$_.Get($default_variable$);\n"
" }\n"
" return *$default_variable$;\n"
"}\n"
- "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+ "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -442,7 +451,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "inline void $classname$::set_$name$(const char* value) {\n"
+ "$inline$ void $classname$::set_$name$(const char* value) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -452,7 +461,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $string_piece$(value), GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
- "inline "
+ "$inline$ "
"void $classname$::set_$name$(const $pointer_type$* value,\n"
" size_t size) {\n"
" if (!has_$name$()) {\n"
@@ -465,7 +474,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
- "inline ::std::string* $classname$::mutable_$name$() {\n"
+ "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -475,7 +484,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
"}\n"
- "inline ::std::string* $classname$::$release_name$() {\n"
+ "$inline$ ::std::string* $classname$::$release_name$() {\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" return $oneof_prefix$$name$_.Release($default_variable$,\n"
@@ -484,7 +493,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" return NULL;\n"
" }\n"
"}\n"
- "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+ "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
@@ -494,7 +503,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" return NULL;\n"
" }\n"
"}\n"
- "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
" if (!has_$name$()) {\n"
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
" }\n"
@@ -506,7 +515,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" }\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n"
- "inline void $classname$::unsafe_arena_set_allocated_$name$("
+ "$inline$ void $classname$::unsafe_arena_set_allocated_$name$("
"::std::string* $name$) {\n"
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
" if (!has_$name$()) {\n"
@@ -522,15 +531,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"}\n");
} else {
// No-arena case.
- printer->Print(variables_,
- "inline const ::std::string& $classname$::$name$() const {\n"
+ printer->Print(variables,
+ "$inline$ const ::std::string& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" if (has_$name$()) {\n"
" return $oneof_prefix$$name$_.GetNoArena($default_variable$);\n"
" }\n"
" return *$default_variable$;\n"
"}\n"
- "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+ "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
@@ -540,7 +549,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $oneof_prefix$$name$_.SetNoArena($default_variable$, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "inline void $classname$::set_$name$(const char* value) {\n"
+ "$inline$ void $classname$::set_$name$(const char* value) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -550,7 +559,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $string_piece$(value));\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
- "inline "
+ "$inline$ "
"void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
@@ -561,7 +570,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" reinterpret_cast<const char*>(value), size));\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
- "inline ::std::string* $classname$::mutable_$name$() {\n"
+ "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -570,7 +579,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $oneof_prefix$$name$_.MutableNoArena($default_variable$);\n"
"}\n"
- "inline ::std::string* $classname$::$release_name$() {\n"
+ "$inline$ ::std::string* $classname$::$release_name$() {\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" return $oneof_prefix$$name$_.ReleaseNoArena($default_variable$);\n"
@@ -578,7 +587,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" return NULL;\n"
" }\n"
"}\n"
- "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
" if (!has_$name$()) {\n"
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
" }\n"
@@ -670,7 +679,10 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedStringFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
// See comment above about unknown ctypes.
- if (descriptor_->options().ctype() != FieldOptions::STRING) {
+ bool unknown_ctype =
+ descriptor_->options().ctype() != EffectiveStringCType(descriptor_);
+
+ if (unknown_ctype) {
printer->Outdent();
printer->Print(
" private:\n"
@@ -679,26 +691,26 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
}
printer->Print(variables_,
- "inline const ::std::string& $name$(int index) const$deprecation$;\n"
- "inline ::std::string* mutable_$name$(int index)$deprecation$;\n"
- "inline void set_$name$(int index, const ::std::string& value)$deprecation$;\n"
- "inline void set_$name$(int index, const char* value)$deprecation$;\n"
- "inline "
+ "const ::std::string& $name$(int index) const$deprecation$;\n"
+ "::std::string* mutable_$name$(int index)$deprecation$;\n"
+ "void set_$name$(int index, const ::std::string& value)$deprecation$;\n"
+ "void set_$name$(int index, const char* value)$deprecation$;\n"
+ ""
"void set_$name$(int index, const $pointer_type$* value, size_t size)"
"$deprecation$;\n"
- "inline ::std::string* add_$name$()$deprecation$;\n"
- "inline void add_$name$(const ::std::string& value)$deprecation$;\n"
- "inline void add_$name$(const char* value)$deprecation$;\n"
- "inline void add_$name$(const $pointer_type$* value, size_t size)"
+ "::std::string* add_$name$()$deprecation$;\n"
+ "void add_$name$(const ::std::string& value)$deprecation$;\n"
+ "void add_$name$(const char* value)$deprecation$;\n"
+ "void add_$name$(const $pointer_type$* value, size_t size)"
"$deprecation$;\n");
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
+ "const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
"$deprecation$;\n"
- "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
+ "::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
"$deprecation$;\n");
- if (descriptor_->options().ctype() != FieldOptions::STRING) {
+ if (unknown_ctype) {
printer->Outdent();
printer->Print(" public:\n");
printer->Indent();
@@ -706,54 +718,57 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
}
void RepeatedStringFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline const ::std::string& $classname$::$name$(int index) const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ const ::std::string& $classname$::$name$(int index) const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.$cppget$(index);\n"
"}\n"
- "inline ::std::string* $classname$::mutable_$name$(int index) {\n"
+ "$inline$ ::std::string* $classname$::mutable_$name$(int index) {\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_.Mutable(index);\n"
"}\n"
- "inline void $classname$::set_$name$(int index, const ::std::string& value) {\n"
+ "$inline$ void $classname$::set_$name$(int index, const ::std::string& value) {\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
" $name$_.Mutable(index)->assign(value);\n"
"}\n"
- "inline void $classname$::set_$name$(int index, const char* value) {\n"
+ "$inline$ void $classname$::set_$name$(int index, const char* value) {\n"
" $name$_.Mutable(index)->assign(value);\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
- "inline void "
+ "$inline$ void "
"$classname$::set_$name$"
"(int index, const $pointer_type$* value, size_t size) {\n"
" $name$_.Mutable(index)->assign(\n"
" reinterpret_cast<const char*>(value), size);\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
- "inline ::std::string* $classname$::add_$name$() {\n"
+ "$inline$ ::std::string* $classname$::add_$name$() {\n"
" return $name$_.Add();\n"
"}\n"
- "inline void $classname$::add_$name$(const ::std::string& value) {\n"
+ "$inline$ void $classname$::add_$name$(const ::std::string& value) {\n"
" $name$_.Add()->assign(value);\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n"
- "inline void $classname$::add_$name$(const char* value) {\n"
+ "$inline$ void $classname$::add_$name$(const char* value) {\n"
" $name$_.Add()->assign(value);\n"
" // @@protoc_insertion_point(field_add_char:$full_name$)\n"
"}\n"
- "inline void "
+ "$inline$ void "
"$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
" $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
" // @@protoc_insertion_point(field_add_pointer:$full_name$)\n"
"}\n");
- printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
+ printer->Print(variables,
+ "$inline$ const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
+ "$inline$ ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$name$_;\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h
index 0a5ca440..d1f19cd9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -54,7 +54,8 @@ class StringFieldGenerator : public FieldGenerator {
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateStaticMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
@@ -83,7 +84,8 @@ class StringOneofFieldGenerator : public StringFieldGenerator {
~StringOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
@@ -103,7 +105,8 @@ class RepeatedStringFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
index 4fa3c144..4e25b2ea 100644
--- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -131,6 +131,24 @@ message TestConflictingSymbolNamesExtension { // NO_PROTO3
} // NO_PROTO3
} // NO_PROTO3
+message TestConflictingEnumNames { // NO_PROTO3
+ enum NestedConflictingEnum { // NO_PROTO3
+ and = 1; // NO_PROTO3
+ class = 2; // NO_PROTO3
+ int = 3; // NO_PROTO3
+ typedef = 4; // NO_PROTO3
+ XOR = 5; // NO_PROTO3
+ } // NO_PROTO3
+
+ optional NestedConflictingEnum conflicting_enum = 1; // NO_PROTO3
+} // NO_PROTO3
+
+enum ConflictingEnum { // NO_PROTO3
+ NOT_EQ = 1; // NO_PROTO3
+ volatile = 2; // NO_PROTO3
+ return = 3; // NO_PROTO3
+} // NO_PROTO3
+
message DummyMessage {}
service TestConflictingMethodNames {
diff --git a/src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto b/src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto
new file mode 100644
index 00000000..cb6ca1b1
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto
@@ -0,0 +1,43 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that proto2 compiler can generate valid code when the enum value
+// is INT_MAX. Note that this is a compile-only test and this proto is not
+// referenced in any C++ code.
+syntax = "proto2";
+
+package protobuf_unittest;
+
+message TestLargeEnumValue {
+ enum EnumWithLargeValue {
+ VALUE_1 = 1;
+ VALUE_MAX = 0x7fffffff;
+ }
+}
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 2a04b293..bd1c0fde 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -55,6 +55,7 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/unittest_optimize_for.pb.h>
#include <google/protobuf/unittest_embed_optimize_for.pb.h>
+#include <google/protobuf/unittest_enormous_descriptor.pb.h>
#include <google/protobuf/unittest_no_generic_services.pb.h>
#include <google/protobuf/test_util.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
@@ -130,6 +131,17 @@ TEST(GeneratedDescriptorTest, IdenticalDescriptors) {
generated_decsriptor_proto.DebugString());
}
+// Test that generated code has proper descriptors:
+// Touch a descriptor generated from an enormous message to validate special
+// handling for descriptors exceeding the C++ standard's recommended minimum
+// limit for string literal size
+TEST(GeneratedDescriptorTest, EnormousDescriptor) {
+ const Descriptor* generated_descriptor =
+ TestEnormousDescriptor::descriptor();
+
+ EXPECT_TRUE(generated_descriptor != NULL);
+}
+
#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
// ===================================================================
@@ -794,6 +806,21 @@ TEST(GeneratedMessageTest, TestConflictingSymbolNames) {
message.GetExtension(ExtensionMessage::repeated_int32_ext, 0));
}
+TEST(GeneratedMessageTest, TestConflictingEnumNames) {
+ protobuf_unittest::TestConflictingEnumNames message;
+ message.set_conflicting_enum(protobuf_unittest::TestConflictingEnumNames_NestedConflictingEnum_and_);
+ EXPECT_EQ(1, message.conflicting_enum());
+ message.set_conflicting_enum(protobuf_unittest::TestConflictingEnumNames_NestedConflictingEnum_XOR);
+ EXPECT_EQ(5, message.conflicting_enum());
+
+
+ protobuf_unittest::ConflictingEnum conflicting_enum;
+ conflicting_enum = protobuf_unittest::NOT_EQ;
+ EXPECT_EQ(1, conflicting_enum);
+ conflicting_enum = protobuf_unittest::return_;
+ EXPECT_EQ(3, conflicting_enum);
+}
+
#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
TEST(GeneratedMessageTest, TestOptimizedForSize) {
@@ -926,6 +953,22 @@ TEST(GeneratedMessageTest, ExtensionConstantValues) {
EXPECT_EQ(unittest::kRepeatedNestedEnumExtensionFieldNumber, 51);
}
+TEST(GeneratedMessageTest, ParseFromTruncated) {
+ const string long_string = string(128, 'q');
+ FileDescriptorProto p;
+ p.add_extension()->set_name(long_string);
+ const string msg = p.SerializeAsString();
+ int successful_count = 0;
+ for (int i = 0; i <= msg.size(); i++) {
+ if (p.ParseFromArray(msg.c_str(), i)) {
+ ++successful_count;
+ }
+ }
+ // We don't really care about how often we succeeded.
+ // As long as we didn't crash, we're happy.
+ EXPECT_GE(successful_count, 1);
+}
+
// ===================================================================
TEST(GeneratedEnumTest, EnumValuesAsSwitchCases) {
@@ -1377,6 +1420,12 @@ class OneofTest : public testing::Test {
case unittest::TestOneof2::kFooString:
EXPECT_TRUE(message.has_foo_string());
break;
+ case unittest::TestOneof2::kFooCord:
+ EXPECT_TRUE(message.has_foo_cord());
+ break;
+ case unittest::TestOneof2::kFooStringPiece:
+ EXPECT_TRUE(message.has_foo_string_piece());
+ break;
case unittest::TestOneof2::kFooBytes:
EXPECT_TRUE(message.has_foo_bytes());
break;
@@ -1389,6 +1438,9 @@ class OneofTest : public testing::Test {
case unittest::TestOneof2::kFoogroup:
EXPECT_TRUE(message.has_foogroup());
break;
+ case unittest::TestOneof2::kFooLazyMessage:
+ EXPECT_TRUE(message.has_foo_lazy_message());
+ break;
case unittest::TestOneof2::FOO_NOT_SET:
break;
}
diff --git a/src/google/protobuf/compiler/cpp/test_large_enum_value.proto b/src/google/protobuf/compiler/cpp/test_large_enum_value.proto
new file mode 100644
index 00000000..cb6ca1b1
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/test_large_enum_value.proto
@@ -0,0 +1,43 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that proto2 compiler can generate valid code when the enum value
+// is INT_MAX. Note that this is a compile-only test and this proto is not
+// referenced in any C++ code.
+syntax = "proto2";
+
+package protobuf_unittest;
+
+message TestLargeEnumValue {
+ enum EnumWithLargeValue {
+ VALUE_1 = 1;
+ VALUE_MAX = 0x7fffffff;
+ }
+}
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc
new file mode 100644
index 00000000..0e8f9836
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc
@@ -0,0 +1,78 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#include <google/protobuf/compiler/csharp/csharp_enum.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+
+using google::protobuf::internal::scoped_ptr;
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) :
+ SourceGeneratorBase(descriptor->file()),
+ descriptor_(descriptor) {
+}
+
+EnumGenerator::~EnumGenerator() {
+}
+
+void EnumGenerator::Generate(io::Printer* printer) {
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print("$access_level$ enum $name$ {\n",
+ "access_level", class_access_level(),
+ "name", descriptor_->name());
+ printer->Indent();
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ printer->Print("$name$ = $number$,\n",
+ "name", descriptor_->value(i)->name(),
+ "number", SimpleItoa(descriptor_->value(i)->number()));
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print("\n");
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.h b/src/google/protobuf/compiler/csharp/csharp_enum.h
new file mode 100644
index 00000000..2cf2fad4
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_enum.h
@@ -0,0 +1,63 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class EnumGenerator : public SourceGeneratorBase {
+ public:
+ EnumGenerator(const EnumDescriptor* descriptor);
+ ~EnumGenerator();
+
+ void Generate(io::Printer* printer);
+
+ private:
+ const EnumDescriptor* descriptor_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__
+
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
new file mode 100644
index 00000000..d38fb1ed
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
@@ -0,0 +1,119 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_enum_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal)
+ : PrimitiveFieldGenerator(descriptor, fieldOrdinal) {
+}
+
+EnumFieldGenerator::~EnumFieldGenerator() {
+}
+
+void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$name$_ = ($type_name$) input.ReadEnum();\n");
+}
+
+void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "if ($has_property_check$) {\n"
+ " output.WriteRawTag($tag_bytes$);\n"
+ " output.WriteEnum((int) $property_name$);\n"
+ "}\n");
+}
+
+void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n"
+ "}\n");
+}
+
+void EnumFieldGenerator::GenerateCodecCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x)");
+}
+
+EnumOneofFieldGenerator::EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal)
+ : PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal) {
+}
+
+EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {
+}
+
+void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ // TODO(jonskeet): What about if we read the default value?
+ printer->Print(
+ variables_,
+ "$oneof_name$_ = input.ReadEnum();\n"
+ "$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n");
+}
+
+void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " output.WriteRawTag($tag_bytes$);\n"
+ " output.WriteEnum((int) $property_name$);\n"
+ "}\n");
+}
+
+void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n"
+ "}\n");
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h
new file mode 100644
index 00000000..08364157
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h
@@ -0,0 +1,77 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class EnumFieldGenerator : public PrimitiveFieldGenerator {
+ public:
+ EnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ ~EnumFieldGenerator();
+
+ virtual void GenerateCodecCode(io::Printer* printer);
+ virtual void GenerateParsingCode(io::Printer* printer);
+ virtual void GenerateSerializationCode(io::Printer* printer);
+ virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
+};
+
+class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator {
+ public:
+ EnumOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ ~EnumOneofFieldGenerator();
+
+ virtual void GenerateParsingCode(io::Printer* printer);
+ virtual void GenerateSerializationCode(io::Printer* printer);
+ virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator);
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__
+
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
new file mode 100644
index 00000000..cd29bcf9
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
@@ -0,0 +1,425 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <limits>
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/mathlimits.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/wire_format.h>
+
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_names.h>
+
+using google::protobuf::internal::scoped_ptr;
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+void FieldGeneratorBase::SetCommonFieldVariables(
+ map<string, string>* variables) {
+ // Note: this will be valid even though the tag emitted for packed and unpacked versions of
+ // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which
+ // never effects the tag size.
+ int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
+ uint tag = internal::WireFormat::MakeTag(descriptor_);
+ uint8 tag_array[5];
+ io::CodedOutputStream::WriteTagToArray(tag, tag_array);
+ string tag_bytes = SimpleItoa(tag_array[0]);
+ for (int i = 1; i < tag_size; i++) {
+ tag_bytes += ", " + SimpleItoa(tag_array[i]);
+ }
+
+ (*variables)["access_level"] = class_access_level();
+ (*variables)["tag"] = SimpleItoa(tag);
+ (*variables)["tag_size"] = SimpleItoa(tag_size);
+ (*variables)["tag_bytes"] = tag_bytes;
+
+ (*variables)["property_name"] = property_name();
+ (*variables)["type_name"] = type_name();
+ (*variables)["name"] = name();
+ (*variables)["descriptor_name"] = descriptor_->name();
+ (*variables)["default_value"] = default_value();
+ if (has_default_value()) {
+ (*variables)["name_def_message"] =
+ (*variables)["name"] + "_ = " + (*variables)["default_value"];
+ } else {
+ (*variables)["name_def_message"] = (*variables)["name"] + "_";
+ }
+ (*variables)["capitalized_type_name"] = capitalized_type_name();
+ (*variables)["number"] = number();
+ (*variables)["has_property_check"] =
+ (*variables)["property_name"] + " != " + (*variables)["default_value"];
+ (*variables)["other_has_property_check"] = "other." +
+ (*variables)["property_name"] + " != " + (*variables)["default_value"];
+}
+
+void FieldGeneratorBase::SetCommonOneofFieldVariables(
+ map<string, string>* variables) {
+ (*variables)["oneof_name"] = oneof_name();
+ (*variables)["has_property_check"] = oneof_name() + "Case_ == " + oneof_property_name() +
+ "OneofCase." + property_name();
+ (*variables)["oneof_property_name"] = oneof_property_name();
+}
+
+FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
+ int fieldOrdinal)
+ : SourceGeneratorBase(descriptor->file()),
+ descriptor_(descriptor),
+ fieldOrdinal_(fieldOrdinal) {
+ SetCommonFieldVariables(&variables_);
+}
+
+FieldGeneratorBase::~FieldGeneratorBase() {
+}
+
+void FieldGeneratorBase::GenerateFreezingCode(io::Printer* printer) {
+ // No-op: only message fields and repeated fields need
+ // special handling for freezing, so default to not generating any code.
+}
+
+void FieldGeneratorBase::GenerateCodecCode(io::Printer* printer) {
+ // No-op: expect this to be overridden by appropriate types.
+ // Could fail if we get called here though...
+}
+
+void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) {
+ if (descriptor_->options().deprecated())
+ {
+ printer->Print("[global::System.ObsoleteAttribute()]\n");
+ }
+}
+
+void FieldGeneratorBase::AddPublicMemberAttributes(io::Printer* printer) {
+ AddDeprecatedFlag(printer);
+}
+
+std::string FieldGeneratorBase::oneof_property_name() {
+ return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), true);
+}
+
+std::string FieldGeneratorBase::oneof_name() {
+ return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), false);
+}
+
+std::string FieldGeneratorBase::property_name() {
+ return GetPropertyName(descriptor_);
+}
+
+std::string FieldGeneratorBase::name() {
+ return UnderscoresToCamelCase(GetFieldName(descriptor_), false);
+}
+
+std::string FieldGeneratorBase::type_name() {
+ return type_name(descriptor_);
+}
+
+std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) {
+ switch (descriptor->type()) {
+ case FieldDescriptor::TYPE_ENUM:
+ return GetClassName(descriptor->enum_type());
+ case FieldDescriptor::TYPE_MESSAGE:
+ case FieldDescriptor::TYPE_GROUP:
+ if (IsWrapperType(descriptor)) {
+ const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
+ string wrapped_field_type_name = type_name(wrapped_field);
+ // String and ByteString go to the same type; other wrapped types go to the
+ // nullable equivalent.
+ if (wrapped_field->type() == FieldDescriptor::TYPE_STRING ||
+ wrapped_field->type() == FieldDescriptor::TYPE_BYTES) {
+ return wrapped_field_type_name;
+ } else {
+ return wrapped_field_type_name + "?";
+ }
+ }
+ return GetClassName(descriptor->message_type());
+ case FieldDescriptor::TYPE_DOUBLE:
+ return "double";
+ case FieldDescriptor::TYPE_FLOAT:
+ return "float";
+ case FieldDescriptor::TYPE_INT64:
+ return "long";
+ case FieldDescriptor::TYPE_UINT64:
+ return "ulong";
+ case FieldDescriptor::TYPE_INT32:
+ return "int";
+ case FieldDescriptor::TYPE_FIXED64:
+ return "ulong";
+ case FieldDescriptor::TYPE_FIXED32:
+ return "uint";
+ case FieldDescriptor::TYPE_BOOL:
+ return "bool";
+ case FieldDescriptor::TYPE_STRING:
+ return "string";
+ case FieldDescriptor::TYPE_BYTES:
+ return "pb::ByteString";
+ case FieldDescriptor::TYPE_UINT32:
+ return "uint";
+ case FieldDescriptor::TYPE_SFIXED32:
+ return "int";
+ case FieldDescriptor::TYPE_SFIXED64:
+ return "long";
+ case FieldDescriptor::TYPE_SINT32:
+ return "int";
+ case FieldDescriptor::TYPE_SINT64:
+ return "long";
+ default:
+ GOOGLE_LOG(FATAL)<< "Unknown field type.";
+ return "";
+ }
+}
+
+bool FieldGeneratorBase::has_default_value() {
+ switch (descriptor_->type()) {
+ case FieldDescriptor::TYPE_ENUM:
+ case FieldDescriptor::TYPE_MESSAGE:
+ case FieldDescriptor::TYPE_GROUP:
+ return true;
+ case FieldDescriptor::TYPE_DOUBLE:
+ return descriptor_->default_value_double() != 0.0;
+ case FieldDescriptor::TYPE_FLOAT:
+ return descriptor_->default_value_float() != 0.0;
+ case FieldDescriptor::TYPE_INT64:
+ return descriptor_->default_value_int64() != 0L;
+ case FieldDescriptor::TYPE_UINT64:
+ return descriptor_->default_value_uint64() != 0L;
+ case FieldDescriptor::TYPE_INT32:
+ return descriptor_->default_value_int32() != 0;
+ case FieldDescriptor::TYPE_FIXED64:
+ return descriptor_->default_value_uint64() != 0L;
+ case FieldDescriptor::TYPE_FIXED32:
+ return descriptor_->default_value_uint32() != 0;
+ case FieldDescriptor::TYPE_BOOL:
+ return descriptor_->default_value_bool();
+ case FieldDescriptor::TYPE_STRING:
+ return true;
+ case FieldDescriptor::TYPE_BYTES:
+ return true;
+ case FieldDescriptor::TYPE_UINT32:
+ return descriptor_->default_value_uint32() != 0;
+ case FieldDescriptor::TYPE_SFIXED32:
+ return descriptor_->default_value_int32() != 0;
+ case FieldDescriptor::TYPE_SFIXED64:
+ return descriptor_->default_value_int64() != 0L;
+ case FieldDescriptor::TYPE_SINT32:
+ return descriptor_->default_value_int32() != 0;
+ case FieldDescriptor::TYPE_SINT64:
+ return descriptor_->default_value_int64() != 0L;
+ default:
+ GOOGLE_LOG(FATAL)<< "Unknown field type.";
+ return true;
+ }
+}
+
+bool FieldGeneratorBase::is_nullable_type() {
+ switch (descriptor_->type()) {
+ case FieldDescriptor::TYPE_ENUM:
+ case FieldDescriptor::TYPE_DOUBLE:
+ case FieldDescriptor::TYPE_FLOAT:
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_FIXED64:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_BOOL:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_SFIXED32:
+ case FieldDescriptor::TYPE_SFIXED64:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_SINT64:
+ return false;
+
+ case FieldDescriptor::TYPE_MESSAGE:
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_STRING:
+ case FieldDescriptor::TYPE_BYTES:
+ return true;
+
+ default:
+ GOOGLE_LOG(FATAL)<< "Unknown field type.";
+ return true;
+ }
+}
+
+bool AllPrintableAscii(const std::string& text) {
+ for(int i = 0; i < text.size(); i++) {
+ if (text[i] < 0x20 || text[i] > 0x7e) {
+ return false;
+ }
+ }
+ return true;
+}
+
+std::string FieldGeneratorBase::GetStringDefaultValueInternal() {
+ // No other default values needed for proto3...
+ return "\"\"";
+}
+
+std::string FieldGeneratorBase::GetBytesDefaultValueInternal() {
+ // No other default values needed for proto3...
+ return "pb::ByteString.Empty";
+}
+
+std::string FieldGeneratorBase::default_value() {
+ return default_value(descriptor_);
+}
+
+std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
+ switch (descriptor->type()) {
+ case FieldDescriptor::TYPE_ENUM:
+ return type_name() + "." + descriptor->default_value_enum()->name();
+ case FieldDescriptor::TYPE_MESSAGE:
+ case FieldDescriptor::TYPE_GROUP:
+ if (IsWrapperType(descriptor)) {
+ const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
+ return default_value(wrapped_field);
+ } else {
+ return "null";
+ }
+ case FieldDescriptor::TYPE_DOUBLE: {
+ double value = descriptor->default_value_double();
+ if (value == numeric_limits<double>::infinity()) {
+ return "double.PositiveInfinity";
+ } else if (value == -numeric_limits<double>::infinity()) {
+ return "double.NegativeInfinity";
+ } else if (MathLimits<double>::IsNaN(value)) {
+ return "double.NaN";
+ }
+ return SimpleDtoa(value) + "D";
+ }
+ case FieldDescriptor::TYPE_FLOAT: {
+ float value = descriptor->default_value_float();
+ if (value == numeric_limits<float>::infinity()) {
+ return "float.PositiveInfinity";
+ } else if (value == -numeric_limits<float>::infinity()) {
+ return "float.NegativeInfinity";
+ } else if (MathLimits<float>::IsNaN(value)) {
+ return "float.NaN";
+ }
+ return SimpleFtoa(value) + "F";
+ }
+ case FieldDescriptor::TYPE_INT64:
+ return SimpleItoa(descriptor->default_value_int64()) + "L";
+ case FieldDescriptor::TYPE_UINT64:
+ return SimpleItoa(descriptor->default_value_uint64()) + "UL";
+ case FieldDescriptor::TYPE_INT32:
+ return SimpleItoa(descriptor->default_value_int32());
+ case FieldDescriptor::TYPE_FIXED64:
+ return SimpleItoa(descriptor->default_value_uint64()) + "UL";
+ case FieldDescriptor::TYPE_FIXED32:
+ return SimpleItoa(descriptor->default_value_uint32());
+ case FieldDescriptor::TYPE_BOOL:
+ if (descriptor->default_value_bool()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ case FieldDescriptor::TYPE_STRING:
+ return GetStringDefaultValueInternal();
+ case FieldDescriptor::TYPE_BYTES:
+ return GetBytesDefaultValueInternal();
+ case FieldDescriptor::TYPE_UINT32:
+ return SimpleItoa(descriptor->default_value_uint32());
+ case FieldDescriptor::TYPE_SFIXED32:
+ return SimpleItoa(descriptor->default_value_int32());
+ case FieldDescriptor::TYPE_SFIXED64:
+ return SimpleItoa(descriptor->default_value_int64()) + "L";
+ case FieldDescriptor::TYPE_SINT32:
+ return SimpleItoa(descriptor->default_value_int32());
+ case FieldDescriptor::TYPE_SINT64:
+ return SimpleItoa(descriptor->default_value_int64()) + "L";
+ default:
+ GOOGLE_LOG(FATAL)<< "Unknown field type.";
+ return "";
+ }
+}
+
+std::string FieldGeneratorBase::number() {
+ return SimpleItoa(descriptor_->number());
+}
+
+std::string FieldGeneratorBase::capitalized_type_name() {
+ switch (descriptor_->type()) {
+ case FieldDescriptor::TYPE_ENUM:
+ return "Enum";
+ case FieldDescriptor::TYPE_MESSAGE:
+ return "Message";
+ case FieldDescriptor::TYPE_GROUP:
+ return "Group";
+ case FieldDescriptor::TYPE_DOUBLE:
+ return "Double";
+ case FieldDescriptor::TYPE_FLOAT:
+ return "Float";
+ case FieldDescriptor::TYPE_INT64:
+ return "Int64";
+ case FieldDescriptor::TYPE_UINT64:
+ return "UInt64";
+ case FieldDescriptor::TYPE_INT32:
+ return "Int32";
+ case FieldDescriptor::TYPE_FIXED64:
+ return "Fixed64";
+ case FieldDescriptor::TYPE_FIXED32:
+ return "Fixed32";
+ case FieldDescriptor::TYPE_BOOL:
+ return "Bool";
+ case FieldDescriptor::TYPE_STRING:
+ return "String";
+ case FieldDescriptor::TYPE_BYTES:
+ return "Bytes";
+ case FieldDescriptor::TYPE_UINT32:
+ return "UInt32";
+ case FieldDescriptor::TYPE_SFIXED32:
+ return "SFixed32";
+ case FieldDescriptor::TYPE_SFIXED64:
+ return "SFixed64";
+ case FieldDescriptor::TYPE_SINT32:
+ return "SInt32";
+ case FieldDescriptor::TYPE_SINT64:
+ return "SInt64";
+ default:
+ GOOGLE_LOG(FATAL)<< "Unknown field type.";
+ return "";
+ }
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h
new file mode 100644
index 00000000..d83543bd
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h
@@ -0,0 +1,103 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__
+
+#include <string>
+#include <google/protobuf/stubs/strutil.h>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class FieldGeneratorBase : public SourceGeneratorBase {
+ public:
+ FieldGeneratorBase(const FieldDescriptor* descriptor, int fieldOrdinal);
+ ~FieldGeneratorBase();
+
+ virtual void GenerateCloningCode(io::Printer* printer) = 0;
+ virtual void GenerateFreezingCode(io::Printer* printer);
+ virtual void GenerateCodecCode(io::Printer* printer);
+ virtual void GenerateMembers(io::Printer* printer) = 0;
+ virtual void GenerateMergingCode(io::Printer* printer) = 0;
+ virtual void GenerateParsingCode(io::Printer* printer) = 0;
+ virtual void GenerateSerializationCode(io::Printer* printer) = 0;
+ virtual void GenerateSerializedSizeCode(io::Printer* printer) = 0;
+
+ virtual void WriteHash(io::Printer* printer) = 0;
+ virtual void WriteEquals(io::Printer* printer) = 0;
+ // Currently unused, as we use reflection to generate JSON
+ virtual void WriteToString(io::Printer* printer) = 0;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ const int fieldOrdinal_;
+ map<string, string> variables_;
+
+ void AddDeprecatedFlag(io::Printer* printer);
+ void AddNullCheck(io::Printer* printer);
+ void AddNullCheck(io::Printer* printer, const std::string& name);
+
+ void AddPublicMemberAttributes(io::Printer* printer);
+ void SetCommonOneofFieldVariables(map<string, string>* variables);
+
+ std::string oneof_property_name();
+ std::string oneof_name();
+ std::string property_name();
+ std::string name();
+ std::string type_name();
+ std::string type_name(const FieldDescriptor* descriptor);
+ bool has_default_value();
+ bool is_nullable_type();
+ std::string default_value();
+ std::string default_value(const FieldDescriptor* descriptor);
+ std::string number();
+ std::string capitalized_type_name();
+
+ private:
+ void SetCommonFieldVariables(map<string, string>* variables);
+ std::string GetStringDefaultValueInternal();
+ std::string GetBytesDefaultValueInternal();
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorBase);
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__
+
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc
new file mode 100644
index 00000000..e0a6c83a
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc
@@ -0,0 +1,100 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+
+#include <google/protobuf/compiler/csharp/csharp_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_umbrella_class.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+
+using google::protobuf::internal::scoped_ptr;
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+std::string GetOutputFile(const google::protobuf::FileDescriptor* file, const std::string file_extension)
+{
+ return GetUmbrellaClassUnqualifiedName(file) + file_extension;
+}
+
+void GenerateFile(const google::protobuf::FileDescriptor* file,
+ io::Printer* printer) {
+ UmbrellaClassGenerator umbrellaGenerator(file);
+ umbrellaGenerator.Generate(printer);
+}
+
+bool Generator::Generate(
+ const FileDescriptor* file,
+ const string& parameter,
+ GeneratorContext* generator_context,
+ string* error) const {
+
+ vector<pair<string, string> > options;
+ ParseGeneratorParameter(parameter, &options);
+
+ // We only support proto3 - but we make an exception for descriptor.proto.
+ if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 && !IsDescriptorProto(file)) {
+ *error = "C# code generation only supports proto3 syntax";
+ return false;
+ }
+
+ std::string file_extension = ".cs";
+ for (int i = 0; i < options.size(); i++) {
+ if (options[i].first == "file_extension") {
+ file_extension = options[i].second;
+ } else {
+ *error = "Unknown generator option: " + options[i].first;
+ return false;
+ }
+ }
+
+ std::string filename = GetOutputFile(file, file_extension);
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(filename));
+ io::Printer printer(output.get(), '$');
+
+ GenerateFile(file, &printer);
+
+ return true;
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.h b/src/google/protobuf/compiler/csharp/csharp_generator.h
new file mode 100644
index 00000000..9b54e914
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.h
@@ -0,0 +1,58 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class LIBPROTOC_EXPORT Generator
+ : public google::protobuf::compiler::CodeGenerator {
+ virtual bool Generate(
+ const FileDescriptor* file,
+ const string& parameter,
+ GeneratorContext* generator_context,
+ string* error) const;
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
+
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
new file mode 100644
index 00000000..7ef7df42
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
@@ -0,0 +1,54 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <memory>
+
+#include <google/protobuf/compiler/ruby/ruby_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/file.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+namespace {
+
+// TODO(jtattermusch): add some tests.
+
+} // namespace
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
new file mode 100644
index 00000000..d25dcba9
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
@@ -0,0 +1,393 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <algorithm>
+#include <google/protobuf/stubs/hash.h>
+#include <limits>
+#include <vector>
+
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+#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_primitive_field.h>
+#include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
+#include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h>
+#include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h>
+#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+CSharpType GetCSharpType(FieldDescriptor::Type type) {
+ switch (type) {
+ case FieldDescriptor::TYPE_INT32:
+ return CSHARPTYPE_INT32;
+ case FieldDescriptor::TYPE_INT64:
+ return CSHARPTYPE_INT64;
+ case FieldDescriptor::TYPE_UINT32:
+ return CSHARPTYPE_UINT32;
+ case FieldDescriptor::TYPE_UINT64:
+ return CSHARPTYPE_UINT32;
+ case FieldDescriptor::TYPE_SINT32:
+ return CSHARPTYPE_INT32;
+ case FieldDescriptor::TYPE_SINT64:
+ return CSHARPTYPE_INT64;
+ case FieldDescriptor::TYPE_FIXED32:
+ return CSHARPTYPE_UINT32;
+ case FieldDescriptor::TYPE_FIXED64:
+ return CSHARPTYPE_UINT64;
+ case FieldDescriptor::TYPE_SFIXED32:
+ return CSHARPTYPE_INT32;
+ case FieldDescriptor::TYPE_SFIXED64:
+ return CSHARPTYPE_INT64;
+ case FieldDescriptor::TYPE_FLOAT:
+ return CSHARPTYPE_FLOAT;
+ case FieldDescriptor::TYPE_DOUBLE:
+ return CSHARPTYPE_DOUBLE;
+ case FieldDescriptor::TYPE_BOOL:
+ return CSHARPTYPE_BOOL;
+ case FieldDescriptor::TYPE_ENUM:
+ return CSHARPTYPE_ENUM;
+ case FieldDescriptor::TYPE_STRING:
+ return CSHARPTYPE_STRING;
+ case FieldDescriptor::TYPE_BYTES:
+ return CSHARPTYPE_BYTESTRING;
+ case FieldDescriptor::TYPE_GROUP:
+ return CSHARPTYPE_MESSAGE;
+ case FieldDescriptor::TYPE_MESSAGE:
+ return CSHARPTYPE_MESSAGE;
+
+ // No default because we want the compiler to complain if any new
+ // types are added.
+ }
+ GOOGLE_LOG(FATAL)<< "Can't get here.";
+ return (CSharpType) -1;
+}
+
+std::string StripDotProto(const std::string& proto_file) {
+ int lastindex = proto_file.find_last_of(".");
+ return proto_file.substr(0, lastindex);
+}
+
+std::string GetFileNamespace(const FileDescriptor* descriptor) {
+ if (descriptor->options().has_csharp_namespace()) {
+ return descriptor->options().csharp_namespace();
+ }
+ return UnderscoresToCamelCase(descriptor->package(), true, true);
+}
+
+std::string GetUmbrellaClassUnqualifiedName(const FileDescriptor* descriptor) {
+ // umbrella_classname can no longer be set using message option.
+ std::string proto_file = descriptor->name();
+ int lastslash = proto_file.find_last_of("/");
+ std::string base = proto_file.substr(lastslash + 1);
+ return UnderscoresToPascalCase(StripDotProto(base));
+}
+
+std::string GetUmbrellaClassNestedNamespace(const FileDescriptor* descriptor) {
+ // TODO(jtattermusch): reintroduce csharp_umbrella_namespace option
+ bool collision = false;
+ std::string umbrella_classname = GetUmbrellaClassUnqualifiedName(descriptor);
+ for(int i = 0; i < descriptor->message_type_count(); i++) {
+ if (descriptor->message_type(i)->name() == umbrella_classname) {
+ collision = true;
+ break;
+ }
+ }
+ for (int i = 0; i < descriptor->service_count(); i++) {
+ if (descriptor->service(i)->name() == umbrella_classname) {
+ collision = true;
+ break;
+ }
+ }
+ for (int i = 0; i < descriptor->enum_type_count(); i++) {
+ if (descriptor->enum_type(i)->name() == umbrella_classname) {
+ collision = true;
+ break;
+ }
+ }
+ return collision ? "Proto" : "";
+}
+
+// TODO(jtattermusch): can we reuse a utility function?
+std::string UnderscoresToCamelCase(const std::string& input,
+ bool cap_next_letter,
+ bool preserve_period) {
+ string result;
+ // Note: I distrust ctype.h due to locales.
+ for (int i = 0; i < input.size(); i++) {
+ if ('a' <= input[i] && input[i] <= 'z') {
+ if (cap_next_letter) {
+ result += input[i] + ('A' - 'a');
+ } else {
+ result += input[i];
+ }
+ cap_next_letter = false;
+ } else if ('A' <= input[i] && input[i] <= 'Z') {
+ if (i == 0 && !cap_next_letter) {
+ // Force first letter to lower-case unless explicitly told to
+ // capitalize it.
+ result += input[i] + ('a' - 'A');
+ } else {
+ // Capital letters after the first are left as-is.
+ result += input[i];
+ }
+ cap_next_letter = false;
+ } else if ('0' <= input[i] && input[i] <= '9') {
+ result += input[i];
+ cap_next_letter = true;
+ } else {
+ cap_next_letter = true;
+ if (input[i] == '.' && preserve_period) {
+ result += '.';
+ }
+ }
+ }
+ // Add a trailing "_" if the name should be altered.
+ if (input[input.size() - 1] == '#') {
+ result += '_';
+ }
+ return result;
+}
+
+std::string UnderscoresToPascalCase(const std::string& input) {
+ return UnderscoresToCamelCase(input, true);
+}
+
+std::string ToCSharpName(const std::string& name, const FileDescriptor* file) {
+ std::string result = GetFileNamespace(file);
+ if (result != "") {
+ result += '.';
+ }
+ string classname;
+ if (file->package().empty()) {
+ classname = name;
+ } else {
+ // Strip the proto package from full_name since we've replaced it with
+ // the C# namespace.
+ classname = name.substr(file->package().size() + 1);
+ }
+ result += StringReplace(classname, ".", ".Types.", true);
+ return "global::" + result;
+}
+
+std::string GetUmbrellaClassName(const FileDescriptor* descriptor) {
+ std::string result = GetFileNamespace(descriptor);
+ if (!result.empty()) {
+ result += '.';
+ }
+ std::string umbrellaNamespace = GetUmbrellaClassNestedNamespace(descriptor);
+ if (!umbrellaNamespace.empty()) {
+ result += umbrellaNamespace + ".";
+ }
+ result += GetUmbrellaClassUnqualifiedName(descriptor);
+ return "global::" + result;
+}
+
+std::string GetClassName(const Descriptor* descriptor) {
+ return ToCSharpName(descriptor->full_name(), descriptor->file());
+}
+
+std::string GetClassName(const EnumDescriptor* descriptor) {
+ return ToCSharpName(descriptor->full_name(), descriptor->file());
+}
+
+// Groups are hacky: The name of the field is just the lower-cased name
+// of the group type. In C#, though, we would like to retain the original
+// capitalization of the type name.
+std::string GetFieldName(const FieldDescriptor* descriptor) {
+ if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
+ return descriptor->message_type()->name();
+ } else {
+ return descriptor->name();
+ }
+}
+
+std::string GetFieldConstantName(const FieldDescriptor* field) {
+ return GetPropertyName(field) + "FieldNumber";
+}
+
+std::string GetPropertyName(const FieldDescriptor* descriptor) {
+ // TODO(jtattermusch): consider introducing csharp_property_name field option
+ std::string property_name = UnderscoresToPascalCase(GetFieldName(descriptor));
+ // Avoid either our own type name or reserved names. Note that not all names
+ // are reserved - a field called to_string, write_to etc would still cause a problem.
+ // There are various ways of ending up with naming collisions, but we try to avoid obvious
+ // ones.
+ if (property_name == descriptor->containing_type()->name()
+ || property_name == "Types"
+ || property_name == "Descriptor") {
+ property_name += "_";
+ }
+ return property_name;
+}
+
+// TODO: c&p from Java protoc plugin
+// For encodings with fixed sizes, returns that size in bytes. Otherwise
+// returns -1.
+int GetFixedSize(FieldDescriptor::Type type) {
+ switch (type) {
+ case FieldDescriptor::TYPE_INT32 : return -1;
+ case FieldDescriptor::TYPE_INT64 : return -1;
+ case FieldDescriptor::TYPE_UINT32 : return -1;
+ case FieldDescriptor::TYPE_UINT64 : return -1;
+ case FieldDescriptor::TYPE_SINT32 : return -1;
+ case FieldDescriptor::TYPE_SINT64 : return -1;
+ case FieldDescriptor::TYPE_FIXED32 : return internal::WireFormatLite::kFixed32Size;
+ case FieldDescriptor::TYPE_FIXED64 : return internal::WireFormatLite::kFixed64Size;
+ case FieldDescriptor::TYPE_SFIXED32: return internal::WireFormatLite::kSFixed32Size;
+ case FieldDescriptor::TYPE_SFIXED64: return internal::WireFormatLite::kSFixed64Size;
+ case FieldDescriptor::TYPE_FLOAT : return internal::WireFormatLite::kFloatSize;
+ case FieldDescriptor::TYPE_DOUBLE : return internal::WireFormatLite::kDoubleSize;
+
+ case FieldDescriptor::TYPE_BOOL : return internal::WireFormatLite::kBoolSize;
+ case FieldDescriptor::TYPE_ENUM : return -1;
+
+ case FieldDescriptor::TYPE_STRING : return -1;
+ case FieldDescriptor::TYPE_BYTES : return -1;
+ case FieldDescriptor::TYPE_GROUP : return -1;
+ case FieldDescriptor::TYPE_MESSAGE : return -1;
+
+ // No default because we want the compiler to complain if any new
+ // types are added.
+ }
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return -1;
+}
+
+static const char base64_chars[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+std::string StringToBase64(const std::string& input) {
+ std::string result;
+ size_t remaining = input.size();
+ const unsigned char *src = (const unsigned char*) input.c_str();
+ while (remaining > 2) {
+ result += base64_chars[src[0] >> 2];
+ result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)];
+ result += base64_chars[((src[1] & 0xf) << 2) | (src[2] >> 6)];
+ result += base64_chars[src[2] & 0x3f];
+ remaining -= 3;
+ src += 3;
+ }
+ switch (remaining) {
+ case 2:
+ result += base64_chars[src[0] >> 2];
+ result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)];
+ result += base64_chars[(src[1] & 0xf) << 2];
+ result += '=';
+ src += 2;
+ break;
+ case 1:
+ result += base64_chars[src[0] >> 2];
+ result += base64_chars[((src[0] & 0x3) << 4)];
+ result += '=';
+ result += '=';
+ src += 1;
+ break;
+ }
+ return result;
+}
+
+std::string FileDescriptorToBase64(const FileDescriptor* descriptor) {
+ std::string fdp_bytes;
+ FileDescriptorProto fdp;
+ descriptor->CopyTo(&fdp);
+ fdp.SerializeToString(&fdp_bytes);
+ return StringToBase64(fdp_bytes);
+}
+
+FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal) {
+ switch (descriptor->type()) {
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_MESSAGE:
+ if (descriptor->is_repeated()) {
+ if (descriptor->is_map()) {
+ return new MapFieldGenerator(descriptor, fieldOrdinal);
+ } else {
+ return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal);
+ }
+ } else {
+ if (IsWrapperType(descriptor)) {
+ if (descriptor->containing_oneof()) {
+ return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal);
+ } else {
+ return new WrapperFieldGenerator(descriptor, fieldOrdinal);
+ }
+ } else {
+ if (descriptor->containing_oneof()) {
+ return new MessageOneofFieldGenerator(descriptor, fieldOrdinal);
+ } else {
+ return new MessageFieldGenerator(descriptor, fieldOrdinal);
+ }
+ }
+ }
+ case FieldDescriptor::TYPE_ENUM:
+ if (descriptor->is_repeated()) {
+ return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal);
+ } else {
+ if (descriptor->containing_oneof()) {
+ return new EnumOneofFieldGenerator(descriptor, fieldOrdinal);
+ } else {
+ return new EnumFieldGenerator(descriptor, fieldOrdinal);
+ }
+ }
+ default:
+ if (descriptor->is_repeated()) {
+ return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal);
+ } else {
+ if (descriptor->containing_oneof()) {
+ return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal);
+ } else {
+ return new PrimitiveFieldGenerator(descriptor, fieldOrdinal);
+ }
+ }
+ }
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h
new file mode 100644
index 00000000..1d17af61
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h
@@ -0,0 +1,132 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
+
+#include <string>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class FieldGeneratorBase;
+
+// TODO: start using this enum.
+enum CSharpType {
+ CSHARPTYPE_INT32 = 1,
+ CSHARPTYPE_INT64 = 2,
+ CSHARPTYPE_UINT32 = 3,
+ CSHARPTYPE_UINT64 = 4,
+ CSHARPTYPE_FLOAT = 5,
+ CSHARPTYPE_DOUBLE = 6,
+ CSHARPTYPE_BOOL = 7,
+ CSHARPTYPE_STRING = 8,
+ CSHARPTYPE_BYTESTRING = 9,
+ CSHARPTYPE_MESSAGE = 10,
+ CSHARPTYPE_ENUM = 11,
+ MAX_CSHARPTYPE = 11
+};
+
+// Converts field type to corresponding C# type.
+CSharpType GetCSharpType(FieldDescriptor::Type type);
+
+std::string StripDotProto(const std::string& proto_file);
+
+// Gets unqualified name of the umbrella class
+std::string GetUmbrellaClassUnqualifiedName(const FileDescriptor* descriptor);
+
+// Gets name of the nested for umbrella class (just the nested part,
+// not including the GetFileNamespace part).
+std::string GetUmbrellaClassNestedNamespace(const FileDescriptor* descriptor);
+
+std::string GetClassName(const Descriptor* descriptor);
+
+std::string GetClassName(const EnumDescriptor* descriptor);
+
+std::string GetFieldName(const FieldDescriptor* descriptor);
+
+std::string GetFieldConstantName(const FieldDescriptor* field);
+
+std::string GetPropertyName(const FieldDescriptor* descriptor);
+
+int GetFixedSize(FieldDescriptor::Type type);
+
+std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter, bool preserve_period);
+
+inline std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter) {
+ return UnderscoresToCamelCase(input, cap_next_letter, false);
+}
+
+std::string UnderscoresToPascalCase(const std::string& input);
+
+// TODO(jtattermusch): perhaps we could move this to strutil
+std::string StringToBase64(const std::string& input);
+
+std::string FileDescriptorToBase64(const FileDescriptor* descriptor);
+
+uint FixedMakeTag(const FieldDescriptor* descriptor);
+
+FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+
+// 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.
+inline bool IsDescriptorProto(const FileDescriptor* descriptor) {
+ // TODO: Do this better! (Currently this depends on a hack in generate_protos.sh to rename
+ // the file...)
+ return descriptor->name() == "google/protobuf/descriptor_proto_file.proto";
+}
+
+inline bool IsWrapperType(const FieldDescriptor* descriptor) {
+ return descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
+ descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto";
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
new file mode 100644
index 00000000..f84ad6f7
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
@@ -0,0 +1,137 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_map_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal)
+ : FieldGeneratorBase(descriptor, fieldOrdinal) {
+}
+
+MapFieldGenerator::~MapFieldGenerator() {
+}
+
+void MapFieldGenerator::GenerateMembers(io::Printer* printer) {
+ const FieldDescriptor* key_descriptor =
+ descriptor_->message_type()->FindFieldByName("key");
+ const FieldDescriptor* value_descriptor =
+ descriptor_->message_type()->FindFieldByName("value");
+ variables_["key_type_name"] = type_name(key_descriptor);
+ variables_["value_type_name"] = type_name(value_descriptor);
+ variables_["true_for_wrappers"] = IsWrapperType(value_descriptor) ? "true" : "";
+ scoped_ptr<FieldGeneratorBase> key_generator(CreateFieldGenerator(key_descriptor, 1));
+ scoped_ptr<FieldGeneratorBase> value_generator(CreateFieldGenerator(value_descriptor, 2));
+
+ printer->Print(
+ variables_,
+ "private static readonly pbc::MapField<$key_type_name$, $value_type_name$>.Codec _map_$name$_codec\n"
+ " = new pbc::MapField<$key_type_name$, $value_type_name$>.Codec(");
+ key_generator->GenerateCodecCode(printer);
+ printer->Print(", ");
+ value_generator->GenerateCodecCode(printer);
+ printer->Print(
+ variables_,
+ ", $tag$);\n"
+ "private readonly pbc::MapField<$key_type_name$, $value_type_name$> $name$_ = new pbc::MapField<$key_type_name$, $value_type_name$>($true_for_wrappers$);\n");
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ pbc::MapField<$key_type_name$, $value_type_name$> $property_name$ {\n"
+ " get { return $name$_; }\n"
+ "}\n");
+}
+
+void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$name$_.Add(other.$name$_);\n");
+}
+
+void MapFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$name$_.AddEntriesFrom(input, _map_$name$_codec);\n");
+}
+
+void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$name$_.WriteTo(output, _map_$name$_codec);\n");
+}
+
+void MapFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "size += $name$_.CalculateSize(_map_$name$_codec);\n");
+}
+
+void MapFieldGenerator::WriteHash(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "hash ^= $property_name$.GetHashCode();\n");
+}
+void MapFieldGenerator::WriteEquals(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if (!$property_name$.Equals(other.$property_name$)) return false;\n");
+}
+
+void MapFieldGenerator::WriteToString(io::Printer* printer) {
+ // TODO: If we ever actually use ToString, we'll need to impleme this...
+}
+
+void MapFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$name$_ = other.$name$_.Clone();\n");
+}
+
+void MapFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.h b/src/google/protobuf/compiler/csharp/csharp_map_field.h
new file mode 100644
index 00000000..f33fe1c3
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.h
@@ -0,0 +1,71 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class MapFieldGenerator : public FieldGeneratorBase {
+ public:
+ MapFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ ~MapFieldGenerator();
+
+ virtual void GenerateCloningCode(io::Printer* printer);
+ virtual void GenerateFreezingCode(io::Printer* printer);
+ virtual void GenerateMembers(io::Printer* printer);
+ virtual void GenerateMergingCode(io::Printer* printer);
+ virtual void GenerateParsingCode(io::Printer* printer);
+ virtual void GenerateSerializationCode(io::Printer* printer);
+ virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+ virtual void WriteHash(io::Printer* printer);
+ virtual void WriteEquals(io::Printer* printer);
+ virtual void WriteToString(io::Printer* printer);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__
+
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc
new file mode 100644
index 00000000..a71a7909
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_message.cc
@@ -0,0 +1,482 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+#include <algorithm>
+#include <map>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite.h>
+
+#include <google/protobuf/compiler/csharp/csharp_enum.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_message.h>
+#include <google/protobuf/compiler/csharp/csharp_names.h>
+
+using google::protobuf::internal::scoped_ptr;
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) {
+ return d1->number() < d2->number();
+}
+
+MessageGenerator::MessageGenerator(const Descriptor* descriptor)
+ : SourceGeneratorBase(descriptor->file()),
+ descriptor_(descriptor) {
+
+ // sorted field names
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_names_.push_back(descriptor_->field(i)->name());
+ }
+ std::sort(field_names_.begin(), field_names_.end());
+
+ // fields by number
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ fields_by_number_.push_back(descriptor_->field(i));
+ }
+ std::sort(fields_by_number_.begin(), fields_by_number_.end(),
+ CompareFieldNumbers);
+}
+
+MessageGenerator::~MessageGenerator() {
+}
+
+std::string MessageGenerator::class_name() {
+ return descriptor_->name();
+}
+
+std::string MessageGenerator::full_class_name() {
+ return GetClassName(descriptor_);
+}
+
+const std::vector<std::string>& MessageGenerator::field_names() {
+ return field_names_;
+}
+
+const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() {
+ return fields_by_number_;
+}
+
+void MessageGenerator::Generate(io::Printer* printer) {
+ map<string, string> vars;
+ vars["class_name"] = class_name();
+ vars["access_level"] = class_access_level();
+
+ printer->Print(
+ "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$> {\n");
+ printer->Indent();
+
+ // All static fields and properties
+ printer->Print(
+ vars,
+ "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n"
+ "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");
+
+ // Access the message descriptor via the relevant file descriptor or containing message descriptor.
+ if (!descriptor_->containing_type()) {
+ vars["descriptor_accessor"] = GetUmbrellaClassName(descriptor_->file())
+ + ".Descriptor.MessageTypes[" + SimpleItoa(descriptor_->index()) + "]";
+ } else {
+ vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type())
+ + ".Descriptor.NestedTypes[" + SimpleItoa(descriptor_->index()) + "]";
+ }
+
+ printer->Print(
+ vars,
+ "public static pbr::MessageDescriptor Descriptor {\n"
+ " get { return $descriptor_accessor$; }\n"
+ "}\n"
+ "\n"
+ "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
+ " get { return Descriptor; }\n"
+ "}\n"
+ "\n");
+
+ // Parameterless constructor and partial OnConstruction method.
+ printer->Print(
+ vars,
+ "public $class_name$() {\n"
+ " OnConstruction();\n"
+ "}\n\n"
+ "partial void OnConstruction();\n\n");
+
+ GenerateCloningCode(printer);
+ GenerateFreezingCode(printer);
+
+ // Fields/properties
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
+
+ // Rats: we lose the debug comment here :(
+ printer->Print(
+ "public const int $field_constant_name$ = $index$;\n",
+ "field_constant_name", GetFieldConstantName(fieldDescriptor),
+ "index", SimpleItoa(fieldDescriptor->number()));
+ scoped_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(fieldDescriptor));
+ generator->GenerateMembers(printer);
+ printer->Print("\n");
+ }
+
+ // oneof properties
+ 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["original_name"] = descriptor_->oneof_decl(i)->name();
+ printer->Print(
+ vars,
+ "private object $name$_;\n"
+ "public enum $property_name$OneofCase {\n");
+ printer->Indent();
+ printer->Print("None = 0,\n");
+ for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+ const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+ printer->Print("$field_property_name$ = $index$,\n",
+ "field_property_name", GetPropertyName(field),
+ "index", SimpleItoa(field->number()));
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print(
+ vars,
+ "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n"
+ "public $property_name$OneofCase $property_name$Case {\n"
+ " get { return $name$Case_; }\n"
+ "}\n\n"
+ "public void Clear$property_name$() {\n"
+ " $name$Case_ = $property_name$OneofCase.None;\n"
+ " $name$_ = null;\n"
+ "}\n\n");
+ }
+
+ // Standard methods
+ GenerateFrameworkMethods(printer);
+ GenerateMessageSerializationMethods(printer);
+ GenerateMergingMethods(printer);
+
+ // Nested messages and enums
+ if (HasNestedGeneratedTypes()) {
+ printer->Print("#region Nested types\n"
+ "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print("public static partial class Types {\n");
+ printer->Indent();
+ for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+ EnumGenerator enumGenerator(descriptor_->enum_type(i));
+ enumGenerator.Generate(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.Generate(printer);
+ }
+ }
+ printer->Outdent();
+ printer->Print("}\n"
+ "#endregion\n"
+ "\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print("\n");
+}
+
+// Helper to work out whether we need to generate a class to hold nested types/enums.
+// Only tricky because we don't want to generate map entry types.
+bool MessageGenerator::HasNestedGeneratedTypes()
+{
+ if (descriptor_->enum_type_count() > 0) {
+ return true;
+ }
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
+ map<string, string> vars;
+ vars["class_name"] = class_name();
+ printer->Print(
+ vars,
+ "public $class_name$($class_name$ other) : this() {\n");
+ printer->Indent();
+ // Clone non-oneof fields first
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!descriptor_->field(i)->containing_oneof()) {
+ scoped_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(descriptor_->field(i)));
+ generator->GenerateCloningCode(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);
+ printer->Print(vars, "switch (other.$property_name$Case) {\n");
+ printer->Indent();
+ for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+ const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+ scoped_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
+ vars["field_property_name"] = GetPropertyName(field);
+ printer->Print(
+ vars,
+ "case $property_name$OneofCase.$field_property_name$:\n");
+ printer->Indent();
+ generator->GenerateCloningCode(printer);
+ printer->Print("break;\n");
+ printer->Outdent();
+ }
+ printer->Outdent();
+ printer->Print("}\n\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ printer->Print(
+ vars,
+ "public $class_name$ Clone() {\n"
+ " return new $class_name$(this);\n"
+ "}\n\n");
+}
+
+void MessageGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
+ map<string, string> vars;
+ vars["class_name"] = class_name();
+
+ // Equality
+ printer->Print(
+ vars,
+ "public override bool Equals(object other) {\n"
+ " return Equals(other as $class_name$);\n"
+ "}\n\n"
+ "public bool Equals($class_name$ other) {\n"
+ " if (ReferenceEquals(other, null)) {\n"
+ " return false;\n"
+ " }\n"
+ " if (ReferenceEquals(other, this)) {\n"
+ " return true;\n"
+ " }\n");
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ scoped_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(descriptor_->field(i)));
+ generator->WriteEquals(printer);
+ }
+ printer->Outdent();
+ printer->Print(
+ " return true;\n"
+ "}\n\n");
+
+ // GetHashCode
+ // Start with a non-zero value to easily distinguish between null and "empty" messages.
+ printer->Print(
+ "public override int GetHashCode() {\n"
+ " int hash = 1;\n");
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ scoped_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(descriptor_->field(i)));
+ generator->WriteHash(printer);
+ }
+ printer->Print("return hash;\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ printer->Print(
+ "public override string ToString() {\n"
+ " return pb::JsonFormatter.Default.Format(this);\n"
+ "}\n\n");
+}
+
+void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) {
+ printer->Print(
+ "public void WriteTo(pb::CodedOutputStream output) {\n");
+ printer->Indent();
+
+ // Serialize all the fields
+ for (int i = 0; i < fields_by_number().size(); i++) {
+ scoped_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(fields_by_number()[i]));
+ generator->GenerateSerializationCode(printer);
+ }
+
+ // TODO(jonskeet): Memoize size of frozen messages?
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n"
+ "public int CalculateSize() {\n");
+ printer->Indent();
+ printer->Print("int size = 0;\n");
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ scoped_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(descriptor_->field(i)));
+ generator->GenerateSerializedSizeCode(printer);
+ }
+ printer->Print("return size;\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
+ // Note: These are separate from GenerateMessageSerializationMethods()
+ // because they need to be generated even for messages that are optimized
+ // for code size.
+ map<string, string> vars;
+ vars["class_name"] = class_name();
+
+ printer->Print(
+ vars,
+ "public void MergeFrom($class_name$ other) {\n");
+ printer->Indent();
+ printer->Print(
+ "if (other == null) {\n"
+ " return;\n"
+ "}\n");
+ // Merge non-oneof fields
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!descriptor_->field(i)->containing_oneof()) {
+ scoped_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(descriptor_->field(i)));
+ generator->GenerateMergingCode(printer);
+ }
+ }
+ // Merge oneof fields
+ 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);
+ printer->Print(vars, "switch (other.$property_name$Case) {\n");
+ printer->Indent();
+ for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+ const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+ vars["field_property_name"] = GetPropertyName(field);
+ printer->Print(
+ vars,
+ "case $property_name$OneofCase.$field_property_name$:\n"
+ " $field_property_name$ = other.$field_property_name$;\n"
+ " break;\n");
+ }
+ printer->Outdent();
+ printer->Print("}\n\n");
+ }
+ printer->Outdent();
+ printer->Print("}\n\n");
+ printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
+ printer->Indent();
+ printer->Print(
+ "uint tag;\n"
+ "while ((tag = input.ReadTag()) != 0) {\n"
+ " switch(tag) {\n");
+ printer->Indent();
+ printer->Indent();
+ printer->Print(
+ "default:\n"
+ " input.SkipLastField();\n" // We're not storing the data, but we still need to consume it.
+ " break;\n");
+ for (int i = 0; i < fields_by_number().size(); i++) {
+ const FieldDescriptor* field = fields_by_number()[i];
+ internal::WireFormatLite::WireType wt =
+ internal::WireFormat::WireTypeForFieldType(field->type());
+ uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt);
+ // Handle both packed and unpacked repeated fields with the same Read*Array call;
+ // the two generated cases are the packed and unpacked tags.
+ // TODO(jonskeet): Check that is_packable is equivalent to is_repeated && wt in { VARINT, FIXED32, FIXED64 }.
+ // It looks like it is...
+ if (field->is_packable()) {
+ printer->Print(
+ "case $packed_tag$:\n",
+ "packed_tag",
+ SimpleItoa(
+ internal::WireFormatLite::MakeTag(
+ field->number(),
+ internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED)));
+ }
+
+ printer->Print("case $tag$: {\n", "tag", SimpleItoa(tag));
+ printer->Indent();
+ scoped_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(field));
+ generator->GenerateParsingCode(printer);
+ printer->Print("break;\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ printer->Outdent();
+ printer->Print("}\n"); // switch
+ printer->Outdent();
+ printer->Print("}\n"); // while
+ printer->Outdent();
+ printer->Print("}\n\n"); // method
+}
+
+int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) {
+ for (int i = 0; i < field_names().size(); i++) {
+ if (field_names()[i] == descriptor->name()) {
+ return i;
+ }
+ }
+ GOOGLE_LOG(DFATAL)<< "Could not find ordinal for field " << descriptor->name();
+ return -1;
+}
+
+FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
+ const FieldDescriptor* descriptor) {
+ return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor));
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h
new file mode 100644
index 00000000..f0c49ac9
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_message.h
@@ -0,0 +1,89 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__
+
+#include <string>
+#include <vector>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class FieldGeneratorBase;
+
+class MessageGenerator : public SourceGeneratorBase {
+ public:
+ MessageGenerator(const Descriptor* descriptor);
+ ~MessageGenerator();
+
+ void GenerateCloningCode(io::Printer* printer);
+ void GenerateFreezingCode(io::Printer* printer);
+ void GenerateFrameworkMethods(io::Printer* printer);
+ void Generate(io::Printer* printer);
+
+ private:
+ const Descriptor* descriptor_;
+ std::vector<std::string> field_names_;
+ std::vector<const FieldDescriptor*> fields_by_number_;
+
+ void GenerateMessageSerializationMethods(io::Printer* printer);
+ void GenerateMergingMethods(io::Printer* printer);
+
+ int GetFieldOrdinal(const FieldDescriptor* descriptor);
+ FieldGeneratorBase* CreateFieldGeneratorInternal(
+ const FieldDescriptor* descriptor);
+
+ bool HasNestedGeneratedTypes();
+
+ std::string class_name();
+ std::string full_class_name();
+
+ // field names sorted alphabetically
+ const std::vector<std::string>& field_names();
+
+ // field descriptors sorted by number
+ const std::vector<const FieldDescriptor*>& fields_by_number();
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
new file mode 100644
index 00000000..4f576cd1
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
@@ -0,0 +1,193 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_message_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal)
+ : FieldGeneratorBase(descriptor, fieldOrdinal) {
+ variables_["has_property_check"] = name() + "_ != null";
+ variables_["has_not_property_check"] = name() + "_ == null";
+}
+
+MessageFieldGenerator::~MessageFieldGenerator() {
+
+}
+
+void MessageFieldGenerator::GenerateMembers(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "private $type_name$ $name$_;\n");
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ $type_name$ $property_name$ {\n"
+ " get { return $name$_; }\n"
+ " set {\n"
+ " $name$_ = value;\n"
+ " }\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if (other.$has_property_check$) {\n"
+ " if ($has_not_property_check$) {\n"
+ " $name$_ = new $type_name$();\n"
+ " }\n"
+ " $property_name$.MergeFrom(other.$property_name$);\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_not_property_check$) {\n"
+ " $name$_ = new $type_name$();\n"
+ "}\n"
+ // TODO(jonskeet): Do we really need merging behaviour like this?
+ "input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP...
+}
+
+void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " output.WriteRawTag($tag_bytes$);\n"
+ " output.WriteMessage($property_name$);\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::WriteHash(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
+}
+void MessageFieldGenerator::WriteEquals(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if (!object.Equals($property_name$, other.$property_name$)) return false;\n");
+}
+void MessageFieldGenerator::WriteToString(io::Printer* printer) {
+ variables_["field_name"] = GetFieldName(descriptor_);
+ printer->Print(
+ variables_,
+ "PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n");
+}
+
+void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$property_name$ = other.$has_property_check$ ? other.$property_name$.Clone() : null;\n");
+}
+
+void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)");
+}
+
+MessageOneofFieldGenerator::MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal)
+ : MessageFieldGenerator(descriptor, fieldOrdinal) {
+ SetCommonOneofFieldVariables(&variables_);
+}
+
+MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {
+
+}
+
+void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ $type_name$ $property_name$ {\n"
+ " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n"
+ " set {\n"
+ " $oneof_name$_ = value;\n"
+ " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
+ " }\n"
+ "}\n");
+}
+
+void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ // TODO(jonskeet): We may be able to do better than this
+ printer->Print(
+ variables_,
+ "$type_name$ subBuilder = new $type_name$();\n"
+ "if ($has_property_check$) {\n"
+ " subBuilder.MergeFrom($property_name$);\n"
+ "}\n"
+ "input.ReadMessage(subBuilder);\n" // No support of TYPE_GROUP
+ "$property_name$ = subBuilder;\n");
+}
+
+void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n");
+}
+
+void MessageOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$property_name$ = other.$property_name$.Clone();\n");
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h
new file mode 100644
index 00000000..dc6e4dc5
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.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_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class MessageFieldGenerator : public FieldGeneratorBase {
+ public:
+ MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ ~MessageFieldGenerator();
+
+ virtual void GenerateCodecCode(io::Printer* printer);
+ virtual void GenerateCloningCode(io::Printer* printer);
+ virtual void GenerateFreezingCode(io::Printer* printer);
+ virtual void GenerateMembers(io::Printer* printer);
+ virtual void GenerateMergingCode(io::Printer* printer);
+ virtual void GenerateParsingCode(io::Printer* printer);
+ virtual void GenerateSerializationCode(io::Printer* printer);
+ virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+ virtual void WriteHash(io::Printer* printer);
+ virtual void WriteEquals(io::Printer* printer);
+ virtual void WriteToString(io::Printer* printer);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
+};
+
+class MessageOneofFieldGenerator : public MessageFieldGenerator {
+ public:
+ MessageOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ ~MessageOneofFieldGenerator();
+
+ virtual void GenerateCloningCode(io::Printer* printer);
+ virtual void GenerateMembers(io::Printer* printer);
+ virtual void WriteToString(io::Printer* printer);
+ virtual void GenerateParsingCode(io::Printer* printer);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__
+
diff --git a/src/google/protobuf/compiler/csharp/csharp_names.h b/src/google/protobuf/compiler/csharp/csharp_names.h
new file mode 100644
index 00000000..ccd2e720
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_names.h
@@ -0,0 +1,82 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Provides a mechanism for mapping a descriptor to the
+// fully-qualified name of the corresponding C# class.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
+
+#include <string>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;
+class EnumDescriptor;
+class FileDescriptor;
+class ServiceDescriptor;
+
+namespace compiler {
+namespace csharp {
+
+// Requires:
+// descriptor != NULL
+//
+// Returns:
+// The namespace to use for given file descriptor.
+string GetFileNamespace(const FileDescriptor* descriptor);
+
+// Requires:
+// descriptor != NULL
+//
+// Returns:
+// The fully-qualified C# class name.
+string GetClassName(const Descriptor* descriptor);
+
+// Requires:
+// descriptor != NULL
+//
+// Returns:
+// The fully-qualified name of the C# class that provides
+// access to the file descriptor. Proto compiler generates
+// such class for each .proto file processed.
+std::string GetUmbrellaClassName(const FileDescriptor* descriptor);
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
new file mode 100644
index 00000000..fc043ec0
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
@@ -0,0 +1,214 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+PrimitiveFieldGenerator::PrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, int fieldOrdinal)
+ : FieldGeneratorBase(descriptor, fieldOrdinal) {
+ // TODO(jonskeet): Make this cleaner...
+ is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING
+ && descriptor->type() != FieldDescriptor::TYPE_BYTES;
+ if (!is_value_type) {
+ variables_["has_property_check"] = variables_["property_name"] + ".Length != 0";
+ variables_["other_has_property_check"] = "other." + variables_["property_name"] + ".Length != 0";
+ }
+}
+
+PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {
+}
+
+void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
+ // TODO(jonskeet): Work out whether we want to prevent the fields from ever being
+ // null, or whether we just handle it, in the cases of bytes and string.
+ // (Basically, should null-handling code be in the getter or the setter?)
+ printer->Print(
+ variables_,
+ "private $type_name$ $name_def_message$;\n");
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ $type_name$ $property_name$ {\n"
+ " get { return $name$_; }\n"
+ " set {\n");
+ if (is_value_type) {
+ printer->Print(
+ variables_,
+ " $name$_ = value;\n");
+ } else {
+ printer->Print(
+ variables_,
+ " $name$_ = pb::Preconditions.CheckNotNull(value, \"value\");\n");
+ }
+ printer->Print(
+ " }\n"
+ "}\n");
+}
+
+void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($other_has_property_check$) {\n"
+ " $property_name$ = other.$property_name$;\n"
+ "}\n");
+}
+
+void PrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ // Note: invoke the property setter rather than writing straight to the field,
+ // so that we can normalize "null to empty" for strings and bytes.
+ printer->Print(
+ variables_,
+ "$property_name$ = input.Read$capitalized_type_name$();\n");
+}
+
+void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " output.WriteRawTag($tag_bytes$);\n"
+ " output.Write$capitalized_type_name$($property_name$);\n"
+ "}\n");
+}
+
+void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n");
+ printer->Indent();
+ int fixedSize = GetFixedSize(descriptor_->type());
+ if (fixedSize == -1) {
+ printer->Print(
+ variables_,
+ "size += $tag_size$ + pb::CodedOutputStream.Compute$capitalized_type_name$Size($property_name$);\n");
+ } else {
+ printer->Print(
+ "size += $tag_size$ + $fixed_size$;\n",
+ "fixed_size", SimpleItoa(fixedSize),
+ "tag_size", variables_["tag_size"]);
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
+}
+void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($property_name$ != other.$property_name$) return false;\n");
+}
+void PrimitiveFieldGenerator::WriteToString(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "PrintField(\"$descriptor_name$\", $has_property_check$, $property_name$, writer);\n");
+}
+
+void PrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$name$_ = other.$name$_;\n");
+}
+
+void PrimitiveFieldGenerator::GenerateCodecCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "pb::FieldCodec.For$capitalized_type_name$($tag$)");
+}
+
+PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
+ const FieldDescriptor* descriptor, int fieldOrdinal)
+ : PrimitiveFieldGenerator(descriptor, fieldOrdinal) {
+ SetCommonOneofFieldVariables(&variables_);
+}
+
+PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {
+}
+
+void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ $type_name$ $property_name$ {\n"
+ " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n"
+ " set {\n");
+ if (is_value_type) {
+ printer->Print(
+ variables_,
+ " $oneof_name$_ = value;\n");
+ } else {
+ printer->Print(
+ variables_,
+ " $oneof_name$_ = pb::Preconditions.CheckNotNull(value, \"value\");\n");
+ }
+ printer->Print(
+ variables_,
+ " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"
+ " }\n"
+ "}\n");
+}
+
+void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) {
+ printer->Print(variables_,
+ "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$property_name$ = input.Read$capitalized_type_name$();\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$property_name$ = other.$property_name$;\n");
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
new file mode 100644
index 00000000..8b87ebc4
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
@@ -0,0 +1,88 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class PrimitiveFieldGenerator : public FieldGeneratorBase {
+ public:
+ PrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ ~PrimitiveFieldGenerator();
+
+ virtual void GenerateCodecCode(io::Printer* printer);
+ virtual void GenerateCloningCode(io::Printer* printer);
+ virtual void GenerateMembers(io::Printer* printer);
+ virtual void GenerateMergingCode(io::Printer* printer);
+ virtual void GenerateParsingCode(io::Printer* printer);
+ virtual void GenerateSerializationCode(io::Printer* printer);
+ virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+ virtual void WriteHash(io::Printer* printer);
+ virtual void WriteEquals(io::Printer* printer);
+ virtual void WriteToString(io::Printer* printer);
+
+ protected:
+ bool is_value_type;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
+};
+
+class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
+ public:
+ PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ ~PrimitiveOneofFieldGenerator();
+
+ virtual void GenerateCloningCode(io::Printer* printer);
+ virtual void GenerateMembers(io::Printer* printer);
+ virtual void WriteToString(io::Printer* printer);
+ virtual void GenerateParsingCode(io::Printer* printer);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__
+
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
new file mode 100644
index 00000000..625631df
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
@@ -0,0 +1,125 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/wire_format.h>
+
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
+ const FieldDescriptor* descriptor, int fieldOrdinal)
+ : FieldGeneratorBase(descriptor, fieldOrdinal) {
+}
+
+RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {
+
+}
+
+void RepeatedEnumFieldGenerator::GenerateMembers(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n"
+ " = pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x);\n");
+ printer->Print(variables_,
+ "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
+ " get { return $name$_; }\n"
+ "}\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$name$_.Add(other.$name$_);\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "size += $name$_.CalculateSize(_repeated_$name$_codec);\n");
+}
+
+void RepeatedEnumFieldGenerator::WriteHash(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "hash ^= $name$_.GetHashCode();\n");
+}
+
+void RepeatedEnumFieldGenerator::WriteEquals(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if(!$name$_.Equals(other.$name$_)) return false;\n");
+}
+
+void RepeatedEnumFieldGenerator::WriteToString(io::Printer* printer) {
+ printer->Print(variables_,
+ "PrintField(\"$descriptor_name$\", $name$_, writer);\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$name$_ = other.$name$_.Clone();\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
new file mode 100644
index 00000000..ee50eef0
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
@@ -0,0 +1,73 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+// TODO(jonskeet): Refactor repeated field support; all the implementations are *really* similar. We
+// should probably have a RepeatedFieldGeneratorBase.
+class RepeatedEnumFieldGenerator : public FieldGeneratorBase {
+ public:
+ RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ ~RepeatedEnumFieldGenerator();
+
+ virtual void GenerateCloningCode(io::Printer* printer);
+ virtual void GenerateFreezingCode(io::Printer* printer);
+ virtual void GenerateMembers(io::Printer* printer);
+ virtual void GenerateMergingCode(io::Printer* printer);
+ virtual void GenerateParsingCode(io::Printer* printer);
+ virtual void GenerateSerializationCode(io::Printer* printer);
+ virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+ virtual void WriteHash(io::Printer* printer);
+ virtual void WriteEquals(io::Printer* printer);
+ virtual void WriteToString(io::Printer* printer);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__
+
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
new file mode 100644
index 00000000..7fbab681
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
@@ -0,0 +1,140 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h>
+#include <google/protobuf/compiler/csharp/csharp_message_field.h>
+#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
+ const FieldDescriptor* descriptor, int fieldOrdinal)
+ : FieldGeneratorBase(descriptor, fieldOrdinal) {
+}
+
+RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {
+
+}
+
+void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n"
+ " = ");
+ // Don't want to duplicate the codec code here... maybe we should have a
+ // "create single field generator for this repeated field"
+ // function, but it doesn't seem worth it for just this.
+ if (IsWrapperType(descriptor_)) {
+ scoped_ptr<FieldGeneratorBase> single_generator(new WrapperFieldGenerator(descriptor_, fieldOrdinal_));
+ single_generator->GenerateCodecCode(printer);
+ } else {
+ scoped_ptr<FieldGeneratorBase> single_generator(new MessageFieldGenerator(descriptor_, fieldOrdinal_));
+ single_generator->GenerateCodecCode(printer);
+ }
+ printer->Print(";\n");
+ printer->Print(
+ variables_,
+ "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
+ " get { return $name$_; }\n"
+ "}\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$name$_.Add(other.$name$_);\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "size += $name$_.CalculateSize(_repeated_$name$_codec);\n");
+}
+
+void RepeatedMessageFieldGenerator::WriteHash(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "hash ^= $name$_.GetHashCode();\n");
+}
+
+void RepeatedMessageFieldGenerator::WriteEquals(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if(!$name$_.Equals(other.$name$_)) return false;\n");
+}
+
+void RepeatedMessageFieldGenerator::WriteToString(io::Printer* printer) {
+ variables_["field_name"] = GetFieldName(descriptor_);
+ printer->Print(
+ variables_,
+ "PrintField(\"$field_name$\", $name$_, writer);\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$name$_ = other.$name$_.Clone();\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
new file mode 100644
index 00000000..cf601c7e
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
@@ -0,0 +1,71 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class RepeatedMessageFieldGenerator : public FieldGeneratorBase {
+ public:
+ RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ ~RepeatedMessageFieldGenerator();
+
+ virtual void GenerateCloningCode(io::Printer* printer);
+ virtual void GenerateFreezingCode(io::Printer* printer);
+ virtual void GenerateMembers(io::Printer* printer);
+ virtual void GenerateMergingCode(io::Printer* printer);
+ virtual void GenerateParsingCode(io::Printer* printer);
+ virtual void GenerateSerializationCode(io::Printer* printer);
+ virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+ virtual void WriteHash(io::Printer* printer);
+ virtual void WriteEquals(io::Printer* printer);
+ virtual void WriteToString(io::Printer* printer);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__
+
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
new file mode 100644
index 00000000..1163ce73
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
@@ -0,0 +1,123 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/wire_format.h>
+
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, int fieldOrdinal)
+ : FieldGeneratorBase(descriptor, fieldOrdinal) {
+}
+
+RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {
+
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n"
+ " = pb::FieldCodec.For$capitalized_type_name$($tag$);\n");
+ printer->Print(variables_,
+ "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
+ " get { return $name$_; }\n"
+ "}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$name$_.Add(other.$name$_);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "size += $name$_.CalculateSize(_repeated_$name$_codec);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::WriteHash(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "hash ^= $name$_.GetHashCode();\n");
+}
+void RepeatedPrimitiveFieldGenerator::WriteEquals(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if(!$name$_.Equals(other.$name$_)) return false;\n");
+}
+void RepeatedPrimitiveFieldGenerator::WriteToString(io::Printer* printer) {
+ printer->Print(variables_,
+ "PrintField(\"$descriptor_name$\", $name$_, writer);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$name$_ = other.$name$_.Clone();\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
new file mode 100644
index 00000000..f1ceeb50
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
@@ -0,0 +1,71 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase {
+ public:
+ RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ ~RepeatedPrimitiveFieldGenerator();
+
+ virtual void GenerateCloningCode(io::Printer* printer);
+ virtual void GenerateFreezingCode(io::Printer* printer);
+ virtual void GenerateMembers(io::Printer* printer);
+ virtual void GenerateMergingCode(io::Printer* printer);
+ virtual void GenerateParsingCode(io::Printer* printer);
+ virtual void GenerateSerializationCode(io::Printer* printer);
+ virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+ virtual void WriteHash(io::Printer* printer);
+ virtual void WriteEquals(io::Printer* printer);
+ virtual void WriteToString(io::Printer* printer);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__
+
diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
new file mode 100644
index 00000000..735d164a
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
@@ -0,0 +1,66 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+
+#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor)
+ : descriptor_(descriptor) {
+}
+
+SourceGeneratorBase::~SourceGeneratorBase() {
+}
+
+void SourceGeneratorBase::WriteGeneratedCodeAttributes(io::Printer* printer) {
+ // This hook can be used to reintroduce generated code attributes in the future.
+}
+
+std::string SourceGeneratorBase::class_access_level() {
+ return IsDescriptorProto(descriptor_) ? "internal" : "public"; // public_classes is always on.
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
new file mode 100644
index 00000000..6caef171
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
@@ -0,0 +1,64 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_SOURCE_GENERATOR_BASE_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_SOURCE_GENERATOR_BASE_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class SourceGeneratorBase {
+ protected:
+ SourceGeneratorBase(const FileDescriptor* descriptor);
+ virtual ~SourceGeneratorBase();
+
+ std::string class_access_level();
+
+ void WriteGeneratedCodeAttributes(io::Printer* printer);
+
+ private:
+ const FileDescriptor* descriptor_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceGeneratorBase);
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_SOURCE_GENERATOR_BASE_H__
+
diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
new file mode 100644
index 00000000..0ffae3d4
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
@@ -0,0 +1,295 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+
+#include <google/protobuf/compiler/csharp/csharp_enum.h>
+#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_umbrella_class.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+UmbrellaClassGenerator::UmbrellaClassGenerator(const FileDescriptor* file)
+ : SourceGeneratorBase(file),
+ file_(file) {
+ namespace_ = GetFileNamespace(file);
+ umbrellaClassname_ = GetUmbrellaClassUnqualifiedName(file);
+ umbrellaNamespace_ = GetUmbrellaClassNestedNamespace(file);
+}
+
+UmbrellaClassGenerator::~UmbrellaClassGenerator() {
+}
+
+void UmbrellaClassGenerator::Generate(io::Printer* printer) {
+ WriteIntroduction(printer);
+
+ WriteDescriptor(printer);
+ // Close the class declaration.
+ printer->Outdent();
+ printer->Print("}\n");
+
+ // Close the namespace around the umbrella class if defined
+ if (!umbrellaNamespace_.empty()) {
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+
+ // write children: Enums
+ if (file_->enum_type_count() > 0) {
+ printer->Print("#region Enums\n");
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ EnumGenerator enumGenerator(file_->enum_type(i));
+ enumGenerator.Generate(printer);
+ }
+ printer->Print("#endregion\n");
+ printer->Print("\n");
+ }
+
+ // write children: Messages
+ if (file_->message_type_count() > 0) {
+ printer->Print("#region Messages\n");
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ MessageGenerator messageGenerator(file_->message_type(i));
+ messageGenerator.Generate(printer);
+ }
+ printer->Print("#endregion\n");
+ printer->Print("\n");
+ }
+
+ // TODO(jtattermusch): add insertion point for services.
+
+ if (!namespace_.empty()) {
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ printer->Print("\n");
+ printer->Print("#endregion Designer generated code\n");
+}
+
+void UmbrellaClassGenerator::WriteIntroduction(io::Printer* printer) {
+ printer->Print(
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $file_name$\n"
+ "#pragma warning disable 1591, 0612, 3021\n"
+ "#region Designer generated code\n"
+ "\n"
+ "using pb = global::Google.Protobuf;\n"
+ "using pbc = global::Google.Protobuf.Collections;\n"
+ "using pbr = global::Google.Protobuf.Reflection;\n"
+ "using scg = global::System.Collections.Generic;\n",
+ "file_name", file_->name());
+
+ if (!namespace_.empty()) {
+ printer->Print("namespace $namespace$ {\n", "namespace", namespace_);
+ printer->Indent();
+ printer->Print("\n");
+ }
+
+ // Add the namespace around the umbrella class if defined
+ if (!umbrellaNamespace_.empty()) {
+ printer->Print("namespace $umbrella_namespace$ {\n",
+ "umbrella_namespace", umbrellaNamespace_);
+ printer->Indent();
+ printer->Print("\n");
+ }
+
+ printer->Print(
+ "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ "$access_level$ static partial class $umbrella_class_name$ {\n"
+ "\n",
+ "access_level", class_access_level(),
+ "umbrella_class_name", umbrellaClassname_);
+ printer->Indent();
+}
+
+void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) {
+ printer->Print(
+ "#region Descriptor\n"
+ "public static pbr::FileDescriptor Descriptor {\n"
+ " get { return descriptor; }\n"
+ "}\n"
+ "private static pbr::FileDescriptor descriptor;\n"
+ "\n"
+ "static $umbrella_class_name$() {\n",
+ "umbrella_class_name", umbrellaClassname_);
+ printer->Indent();
+ printer->Print(
+ "byte[] descriptorData = global::System.Convert.FromBase64String(\n");
+ printer->Indent();
+ printer->Indent();
+ printer->Print("string.Concat(\n");
+ printer->Indent();
+
+ // TODO(jonskeet): Consider a C#-escaping format here instead of just Base64.
+ std::string base64 = FileDescriptorToBase64(file_);
+ while (base64.size() > 60) {
+ printer->Print("\"$base64$\", \n", "base64", base64.substr(0, 60));
+ base64 = base64.substr(60);
+ }
+ printer->Print("\"$base64$\"));\n", "base64", base64);
+ printer->Outdent();
+ printer->Outdent();
+ printer->Outdent();
+
+ // -----------------------------------------------------------------
+ // Invoke InternalBuildGeneratedFileFrom() to build the file.
+ printer->Print(
+ "descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,\n");
+ printer->Print(" new pbr::FileDescriptor[] { ");
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ printer->Print(
+ "$full_umbrella_class_name$.Descriptor, ",
+ "full_umbrella_class_name",
+ GetUmbrellaClassName(file_->dependency(i)));
+ }
+ printer->Print("},\n"
+ " new pbr::GeneratedCodeInfo(");
+ // Specify all the generated code information, recursively.
+ if (file_->enum_type_count() > 0) {
+ printer->Print("new[] {");
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ printer->Print("typeof($type_name$), ", "type_name", GetClassName(file_->enum_type(i)));
+ }
+ printer->Print("}, ");
+ }
+ else {
+ printer->Print("null, ");
+ }
+ if (file_->message_type_count() > 0) {
+ printer->Print("new pbr::GeneratedCodeInfo[] {\n");
+ printer->Indent();
+ printer->Indent();
+ printer->Indent();
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ WriteGeneratedCodeInfo(file_->message_type(i), printer, i == file_->message_type_count() - 1);
+ }
+ printer->Outdent();
+ printer->Print("\n}));\n");
+ printer->Outdent();
+ printer->Outdent();
+ }
+ else {
+ printer->Print("null));\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print("#endregion\n\n");
+}
+
+// Write out the generated code for a particular message. This consists of the CLR type, property names
+// corresponding to fields, names corresponding to oneofs, nested enums, and nested types. Each array part
+// can be specified as null if it would be empty, to make the generated code somewhat simpler to read.
+// We write a line break at the end of each generated code info, so that in the final file we'll see all
+// the types, pre-ordered depth first, one per line. The indentation will be slightly unusual,
+// in that it will look like a single array when it's actually constructing a tree, but it'll be easy to
+// read even with multiple levels of nesting.
+// The "last" parameter indicates whether this message descriptor is the last one being printed in this immediate
+// context. It governs whether or not a trailing comma and newline is written after the constructor, effectively
+// just controlling the formatting in the generated code.
+void UmbrellaClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last) {
+ if (IsMapEntryMessage(descriptor)) {
+ printer->Print("null, ");
+ return;
+ }
+ // Generated message type
+ printer->Print("new pbr::GeneratedCodeInfo(typeof($type_name$), ", "type_name", GetClassName(descriptor));
+
+ // Fields
+ if (descriptor->field_count() > 0) {
+ std::vector<std::string> fields;
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ fields.push_back(GetPropertyName(descriptor->field(i)));
+ }
+ printer->Print("new[]{ \"$fields$\" }, ", "fields", JoinStrings(fields, "\", \""));
+ }
+ else {
+ printer->Print("null, ");
+ }
+
+ // Oneofs
+ if (descriptor->oneof_decl_count() > 0) {
+ std::vector<std::string> oneofs;
+ for (int i = 0; i < descriptor->oneof_decl_count(); i++) {
+ oneofs.push_back(UnderscoresToCamelCase(descriptor->oneof_decl(i)->name(), true));
+ }
+ printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", JoinStrings(oneofs, "\", \""));
+ }
+ else {
+ printer->Print("null, ");
+ }
+
+ // Nested enums
+ if (descriptor->enum_type_count() > 0) {
+ std::vector<std::string> enums;
+ for (int i = 0; i < descriptor->enum_type_count(); i++) {
+ enums.push_back(GetClassName(descriptor->enum_type(i)));
+ }
+ printer->Print("new[]{ typeof($enums$) }, ", "enums", JoinStrings(enums, "), typeof("));
+ }
+ else {
+ printer->Print("null, ");
+ }
+
+ // Nested types
+ if (descriptor->nested_type_count() > 0) {
+ // Need to specify array type explicitly here, as all elements may be null.
+ printer->Print("new pbr::GeneratedCodeInfo[] { ");
+ for (int i = 0; i < descriptor->nested_type_count(); i++) {
+ WriteGeneratedCodeInfo(descriptor->nested_type(i), printer, i == descriptor->nested_type_count() - 1);
+ }
+ printer->Print("}");
+ }
+ else {
+ printer->Print("null");
+ }
+ printer->Print(last ? ")" : "),\n");
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h
new file mode 100644
index 00000000..b8bd2133
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h
@@ -0,0 +1,70 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_UMBRELLA_CLASS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_UMBRELLA_CLASS_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class UmbrellaClassGenerator : public SourceGeneratorBase {
+ public:
+ UmbrellaClassGenerator(const FileDescriptor* file);
+ ~UmbrellaClassGenerator();
+
+ void Generate(io::Printer* printer);
+
+ private:
+ const FileDescriptor* file_;
+
+ std::string namespace_;
+ std::string umbrellaClassname_;
+ std::string umbrellaNamespace_;
+
+ void WriteIntroduction(io::Printer* printer);
+ void WriteDescriptor(io::Printer* printer);
+ void WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last);
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UmbrellaClassGenerator);
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_UMBRELLA_CLASS_H__
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
new file mode 100644
index 00000000..44f832bf
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
@@ -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.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal)
+ : FieldGeneratorBase(descriptor, fieldOrdinal) {
+ variables_["has_property_check"] = name() + "_ != null";
+ variables_["has_not_property_check"] = name() + "_ == null";
+ const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
+ is_value_type = wrapped_field->type() != FieldDescriptor::TYPE_STRING &&
+ wrapped_field->type() != FieldDescriptor::TYPE_BYTES;
+ if (is_value_type) {
+ variables_["nonnullable_type_name"] = type_name(wrapped_field);
+ }
+}
+
+WrapperFieldGenerator::~WrapperFieldGenerator() {
+}
+
+void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "private static readonly pb::FieldCodec<$type_name$> _single_$name$_codec = ");
+ GenerateCodecCode(printer);
+ printer->Print(
+ variables_,
+ ";\n"
+ "private $type_name$ $name$_;\n");
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ $type_name$ $property_name$ {\n"
+ " get { return $name$_; }\n"
+ " set {\n"
+ " $name$_ = value;\n"
+ " }\n"
+ "}\n");
+}
+
+void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if (other.$has_property_check$) {\n"
+ " if ($has_not_property_check$ || other.$property_name$ != $default_value$) {\n"
+ " $property_name$ = other.$property_name$;\n"
+ " }\n"
+ "}\n");
+}
+
+void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$type_name$ value = _single_$name$_codec.Read(input);\n"
+ "if ($has_not_property_check$ || value != $default_value$) {\n"
+ " $property_name$ = value;\n"
+ "}\n");
+}
+
+void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n"
+ "}\n");
+}
+
+void WrapperFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " size += _single_$name$_codec.CalculateSizeWithTag($property_name$);\n"
+ "}\n");
+}
+
+void WrapperFieldGenerator::WriteHash(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
+}
+
+void WrapperFieldGenerator::WriteEquals(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($property_name$ != other.$property_name$) return false;\n");
+}
+
+void WrapperFieldGenerator::WriteToString(io::Printer* printer) {
+ // TODO: Implement if we ever actually need it...
+}
+
+void WrapperFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$property_name$ = other.$property_name$;\n");
+}
+
+void WrapperFieldGenerator::GenerateCodecCode(io::Printer* printer) {
+ if (is_value_type) {
+ printer->Print(
+ variables_,
+ "pb::FieldCodec.ForStructWrapper<$nonnullable_type_name$>($tag$)");
+ } else {
+ printer->Print(
+ variables_,
+ "pb::FieldCodec.ForClassWrapper<$type_name$>($tag$)");
+ }
+}
+
+WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal)
+ : WrapperFieldGenerator(descriptor, fieldOrdinal) {
+ SetCommonOneofFieldVariables(&variables_);
+}
+
+WrapperOneofFieldGenerator::~WrapperOneofFieldGenerator() {
+}
+
+void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
+ // Note: deliberately _oneof_$name$_codec, not _$oneof_name$_codec... we have one codec per field.
+ printer->Print(
+ variables_,
+ "private static readonly pb::FieldCodec<$type_name$> _oneof_$name$_codec = ");
+ GenerateCodecCode(printer);
+ printer->Print(";\n");
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ $type_name$ $property_name$ {\n"
+ " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : ($type_name$) null; }\n"
+ " set {\n"
+ " $oneof_name$_ = value;\n"
+ " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
+ " }\n"
+ "}\n");
+}
+
+void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$property_name$ = _oneof_$name$_codec.Read(input);\n");
+}
+
+void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ // TODO: I suspect this is wrong...
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n"
+ "}\n");
+}
+
+void WrapperOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ // TODO: I suspect this is wrong...
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " size += _oneof_$name$_codec.CalculateSizeWithTag($property_name$);\n"
+ "}\n");
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
new file mode 100644
index 00000000..6e2414af
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
@@ -0,0 +1,85 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class WrapperFieldGenerator : public FieldGeneratorBase {
+ public:
+ WrapperFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ ~WrapperFieldGenerator();
+
+ virtual void GenerateCodecCode(io::Printer* printer);
+ virtual void GenerateCloningCode(io::Printer* printer);
+ virtual void GenerateMembers(io::Printer* printer);
+ virtual void GenerateMergingCode(io::Printer* printer);
+ virtual void GenerateParsingCode(io::Printer* printer);
+ virtual void GenerateSerializationCode(io::Printer* printer);
+ virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+ virtual void WriteHash(io::Printer* printer);
+ virtual void WriteEquals(io::Printer* printer);
+ virtual void WriteToString(io::Printer* printer);
+
+ private:
+ bool is_value_type; // True for int32 etc; false for bytes and string
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WrapperFieldGenerator);
+};
+
+class WrapperOneofFieldGenerator : public WrapperFieldGenerator {
+ public:
+ WrapperOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ ~WrapperOneofFieldGenerator();
+
+ virtual void GenerateMembers(io::Printer* printer);
+ virtual void GenerateParsingCode(io::Printer* printer);
+ virtual void GenerateSerializationCode(io::Printer* printer);
+ virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WrapperOneofFieldGenerator);
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index 71a2ba4b..39318a19 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -67,7 +67,13 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
(*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
(*variables)["default_number"] = SimpleItoa(
descriptor->default_value_enum()->number());
- (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
+ 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_size"] = SimpleItoa(
internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
// TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
@@ -641,7 +647,7 @@ GenerateMembers(io::Printer* printer) const {
"}\n");
}
- if (descriptor_->options().packed() &&
+ if (descriptor_->is_packed() &&
HasGeneratedMethods(descriptor_->containing_type())) {
printer->Print(variables_,
"private int $name$MemoizedSerializedSize;\n");
@@ -884,7 +890,7 @@ GenerateParsingDoneCode(io::Printer* printer) const {
void RepeatedImmutableEnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
"if (get$capitalized_name$List().size() > 0) {\n"
" output.writeRawVarint32($tag$);\n"
@@ -915,7 +921,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
"}\n");
printer->Print(
"size += dataSize;\n");
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
"if (!get$capitalized_name$List().isEmpty()) {"
" size += $tag_size$;\n"
@@ -928,7 +934,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
}
// cache the data size for packed fields.
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
"$name$MemoizedSerializedSize = dataSize;\n");
}
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
new file mode 100644
index 00000000..697a07a7
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
@@ -0,0 +1,967 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum_field_lite.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/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+void SetEnumVariables(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ map<string, string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+
+ (*variables)["type"] =
+ name_resolver->GetImmutableClassName(descriptor->enum_type());
+ (*variables)["mutable_type"] =
+ name_resolver->GetMutableClassName(descriptor->enum_type());
+ (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["default_number"] = SimpleItoa(
+ descriptor->default_value_enum()->number());
+ (*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();" : "";
+
+ if (SupportFieldPresence(descriptor->file())) {
+ // For singular messages and builders, one bit is used for the hasField bit.
+ (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+ // Note that these have a trailing ";".
+ (*variables)["set_has_field_bit_message"] =
+ GenerateSetBit(messageBitIndex) + ";";
+ (*variables)["clear_has_field_bit_message"] =
+ GenerateClearBit(messageBitIndex) + ";";
+
+ (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+ } else {
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["clear_has_field_bit_message"] = "";
+
+ (*variables)["is_field_present_message"] =
+ (*variables)["name"] + "_ != " +
+ (*variables)["default"] + ".getNumber()";
+ }
+
+ // For repeated builders, the underlying list tracks mutability state.
+ (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
+
+ (*variables)["get_has_field_bit_from_local"] =
+ GenerateGetBitFromLocal(builderBitIndex);
+ (*variables)["set_has_field_bit_to_local"] =
+ GenerateSetBitToLocal(messageBitIndex);
+
+ if (SupportUnknownEnumValue(descriptor->file())) {
+ (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED";
+ } else {
+ (*variables)["unknown"] = (*variables)["default"];
+ }
+}
+
+} // namespace
+
+// ===================================================================
+
+ImmutableEnumFieldLiteGenerator::
+ImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+ builderBitIndex_(builderBitIndex),
+ name_resolver_(context->GetNameResolver()) {
+ SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+ImmutableEnumFieldLiteGenerator::~ImmutableEnumFieldLiteGenerator() {}
+
+int ImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 1;
+}
+
+int ImmutableEnumFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$boolean has$capitalized_name$();\n");
+ }
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Value();\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private int $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+ }
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value() {\n"
+ " return $name$_;\n"
+ "}\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " $type$ result = $type$.valueOf($name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
+ "}\n");
+
+ // Generate private setters for the builder to proxy into.
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$Value(int value) {\n"
+ " $set_has_field_bit_message$"
+ " $name$_ = value;\n"
+ "}\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " $set_has_field_bit_message$\n"
+ " $name$_ = value.getNumber();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $clear_has_field_bit_message$\n"
+ " $name$_ = $default_number$;\n"
+ "}\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ }
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value() {\n"
+ " return instance.get$capitalized_name$Value();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$Value(int value);\n"
+ " return this;\n"
+ "}\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // noop for enums
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $default_number$;\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateMergingCode(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");
+ } else if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "if (other.$name$_ != $default_number$) {\n"
+ " set$capitalized_name$Value(other.get$capitalized_name$Value());\n"
+ "}\n");
+ } else {
+ GOOGLE_LOG(FATAL) << "Can't reach here.";
+ }
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ // noop for scalars
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "int rawValue = input.readEnum();\n"
+ "$set_has_field_bit_message$\n"
+ "$name$_ = rawValue;\n");
+ } else {
+ printer->Print(variables_,
+ "int rawValue = input.readEnum();\n"
+ "$type$ value = $type$.valueOf(rawValue);\n"
+ "if (value == null) {\n");
+ if (PreserveUnknownFields(descriptor_->containing_type())) {
+ printer->Print(variables_,
+ " unknownFields.mergeVarintField($number$, rawValue);\n");
+ }
+ printer->Print(variables_,
+ "} else {\n"
+ " $set_has_field_bit_message$\n"
+ " $name$_ = rawValue;\n"
+ "}\n");
+ }
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ // noop for enums
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " output.writeEnum($number$, $name$_);\n"
+ "}\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeEnumSize($number$, $name$_);\n"
+ "}\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = result && $name$_ == other.$name$_;\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n"
+ "hash = (53 * hash) + $name$_;\n");
+}
+
+string ImmutableEnumFieldLiteGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
+}
+
+// ===================================================================
+
+ImmutableEnumOneofFieldLiteGenerator::
+ImmutableEnumOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : ImmutableEnumFieldLiteGenerator(
+ descriptor, messageBitIndex, builderBitIndex, context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableEnumOneofFieldLiteGenerator::
+~ImmutableEnumOneofFieldLiteGenerator() {}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ }
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return (java.lang.Integer) $oneof_name$_;\n"
+ " }\n"
+ " return $default_number$;\n"
+ "}\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ 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"
+ " return result == null ? $unknown$ : result;\n"
+ " }\n"
+ " return $default$;\n"
+ "}\n");
+
+ // Generate private setters for the builder to proxy into.
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$Value(int value) {\n"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ "}\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value.getNumber();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ "}\n");
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ }
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value() {\n"
+ " return instance.get$capitalized_name$Value();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$Value(value);\n"
+ " return this;\n"
+ "}\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+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");
+ }
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "int rawValue = input.readEnum();\n"
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = rawValue;\n");
+ } else {
+ printer->Print(variables_,
+ "int rawValue = input.readEnum();\n"
+ "$type$ value = $type$.valueOf(rawValue);\n"
+ "if (value == null) {\n");
+ if (PreserveUnknownFields(descriptor_->containing_type())) {
+ printer->Print(variables_,
+ " unknownFields.mergeVarintField($number$, rawValue);\n");
+ }
+ printer->Print(variables_,
+ "} else {\n"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = rawValue;\n"
+ "}\n");
+ }
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n"
+ "}\n");
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n"
+ "}\n");
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$Value()\n"
+ " == other.get$capitalized_name$Value();\n");
+ } else {
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$()\n"
+ " .equals(other.get$capitalized_name$());\n");
+ }
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n"
+ "hash = (53 * hash) + get$capitalized_name$Value();\n");
+ } else {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n"
+ "hash = (53 * hash) + get$capitalized_name$().getNumber();\n");
+ }
+}
+
+// ===================================================================
+
+RepeatedImmutableEnumFieldLiteGenerator::
+RepeatedImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+RepeatedImmutableEnumFieldLiteGenerator::
+~RepeatedImmutableEnumFieldLiteGenerator() {}
+
+int RepeatedImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+int RepeatedImmutableEnumFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$(int index);\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<java.lang.Integer>\n"
+ "get$capitalized_name$ValueList();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Value(int index);\n");
+ }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ // TODO(dweis): Switch to IntList?
+ "private com.google.protobuf.Internal.ProtobufList<\n"
+ " java.lang.Integer> $name$_;\n"
+ "private static final com.google.protobuf.Internal.ListAdapter.Converter<\n"
+ " java.lang.Integer, $type$> $name$_converter_ =\n"
+ " new com.google.protobuf.Internal.ListAdapter.Converter<\n"
+ " java.lang.Integer, $type$>() {\n"
+ " public $type$ convert(java.lang.Integer from) {\n"
+ " $type$ result = $type$.valueOf(from);\n"
+ " return result == null ? $unknown$ : result;\n"
+ " }\n"
+ " };\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+ " return new com.google.protobuf.Internal.ListAdapter<\n"
+ " java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+ " return $name$_converter_.convert($name$_.get(index));\n"
+ "}\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<java.lang.Integer>\n"
+ "get$capitalized_name$ValueList() {\n"
+ " return $name$_;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ }
+
+ if (descriptor_->options().packed() &&
+ HasGeneratedMethods(descriptor_->containing_type())) {
+ printer->Print(variables_,
+ "private int $name$MemoizedSerializedSize;\n");
+ }
+
+ // Generate private setters for the builder to proxy into.
+ printer->Print(variables_,
+ "private void ensure$capitalized_name$IsMutable() {\n"
+ " if (!$is_mutable$) {\n"
+ " $name$_ = newProtobufList($name$_);\n"
+ " }\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, value.getNumber());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value.getNumber());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " for ($type$ value : values) {\n"
+ " $name$_.add(value.getNumber());\n"
+ " }\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $name$_ = emptyProtobufList();\n"
+ "}\n");
+
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$Value(\n"
+ " int index, int value) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, value);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$Value(int value) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void addAll$capitalized_name$Value(\n"
+ " java.lang.Iterable<java.lang.Integer> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " for (int value : values) {\n"
+ " $name$_.add(value);\n"
+ " }\n"
+ "}\n");
+ }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+ " return instance.get$capitalized_name$List();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return instance.get$capitalized_name$Count();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+ " return instance.get$capitalized_name$(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$(values);"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<java.lang.Integer>\n"
+ "get$capitalized_name$ValueList() {\n"
+ " return java.util.Collections.unmodifiableList(\n"
+ " instance.get$capitalized_name$ValueList());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+ " return instance.get$capitalized_name$Value(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$Value(\n"
+ " int index, int value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$Value(index, value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$Value(int value) {\n"
+ " instance.add$capitalized_name$Value(value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder addAll$capitalized_name$Value(\n"
+ " java.lang.Iterable<java.lang.Integer> values) {\n"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$Value(values);\n"
+ " return this;\n"
+ "}\n");
+ }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // noop for enums
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = emptyProtobufList();\n");
+}
+
+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");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_.makeImmutable();\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ // Read and store the enum
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "int rawValue = input.readEnum();\n"
+ "if (!$is_mutable$) {\n"
+ " $name$_ = newProtobufList();\n"
+ "}\n"
+ "$name$_.add(rawValue);\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_,
+ " unknownFields.mergeVarintField($number$, rawValue);\n");
+ }
+ printer->Print(variables_,
+ "} else {\n"
+ " if (!$is_mutable$) {\n"
+ " $name$_ = newProtobufList();\n"
+ " }\n"
+ " $name$_.add(rawValue);\n"
+ "}\n");
+ }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ // Wrap GenerateParsingCode's contents with a while loop.
+
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int oldLimit = input.pushLimit(length);\n"
+ "while(input.getBytesUntilLimit() > 0) {\n");
+ printer->Indent();
+
+ GenerateParsingCode(printer);
+
+ printer->Outdent();
+ printer->Print(variables_,
+ "}\n"
+ "input.popLimit(oldLimit);\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_mutable$) {\n"
+ " $name$_.makeImmutable();\n"
+ "}\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (get$capitalized_name$List().size() > 0) {\n"
+ " output.writeRawVarint32($tag$);\n"
+ " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+ "}\n"
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.writeEnumNoTag($name$_.get(i));\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.writeEnum($number$, $name$_.get(i));\n"
+ "}\n");
+ }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "{\n"
+ " int dataSize = 0;\n");
+ printer->Indent();
+
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " dataSize += com.google.protobuf.CodedOutputStream\n"
+ " .computeEnumSizeNoTag($name$_.get(i));\n"
+ "}\n");
+ printer->Print(
+ "size += dataSize;\n");
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (!get$capitalized_name$List().isEmpty()) {"
+ " size += $tag_size$;\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeRawVarint32Size(dataSize);\n"
+ "}");
+ } else {
+ printer->Print(variables_,
+ "size += $tag_size$ * $name$_.size();\n");
+ }
+
+ // cache the data size for packed fields.
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "$name$MemoizedSerializedSize = dataSize;\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = result && $name$_.equals(other.$name$_);\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (get$capitalized_name$Count() > 0) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + $name$_.hashCode();\n"
+ "}\n");
+}
+
+string RepeatedImmutableEnumFieldLiteGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.h b/src/google/protobuf/compiler/java/java_enum_field_lite.h
new file mode 100644
index 00000000..2c41c3e4
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.h
@@ -0,0 +1,159 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ class ClassNameResolver; // name_resolver.h
+ }
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator {
+ public:
+ explicit ImmutableEnumFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableEnumFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ int GetNumBitsForMessage() const;
+ int GetNumBitsForBuilder() const;
+ void GenerateInterfaceMembers(io::Printer* printer) const;
+ 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 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldLiteGenerator);
+};
+
+class ImmutableEnumOneofFieldLiteGenerator
+ : public ImmutableEnumFieldLiteGenerator {
+ public:
+ ImmutableEnumOneofFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableEnumOneofFieldLiteGenerator();
+
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutableEnumFieldLiteGenerator
+ : public ImmutableFieldLiteGenerator {
+ public:
+ explicit RepeatedImmutableEnumFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~RepeatedImmutableEnumFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ int GetNumBitsForMessage() const;
+ int GetNumBitsForBuilder() const;
+ void GenerateInterfaceMembers(io::Printer* printer) const;
+ 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 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc
index 27cf416b..4db7085e 100644
--- a/src/google/protobuf/compiler/java/java_extension.cc
+++ b/src/google/protobuf/compiler/java/java_extension.cc
@@ -181,8 +181,9 @@ void ImmutableExtensionGenerator::Generate(io::Printer* printer) {
}
}
-void ImmutableExtensionGenerator::GenerateNonNestedInitializationCode(
+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.
@@ -190,15 +191,18 @@ void ImmutableExtensionGenerator::GenerateNonNestedInitializationCode(
"$name$.internalInit(descriptor.getExtensions().get($index$));\n",
"name", UnderscoresToCamelCase(descriptor_),
"index", SimpleItoa(descriptor_->index()));
+ bytecode_estimate += 21;
}
+ return bytecode_estimate;
}
-void ImmutableExtensionGenerator::GenerateRegistrationCode(
+int ImmutableExtensionGenerator::GenerateRegistrationCode(
io::Printer* printer) {
printer->Print(
"registry.add($scope$.$name$);\n",
"scope", scope_,
"name", UnderscoresToCamelCase(descriptor_));
+ return 7;
}
} // namespace java
diff --git a/src/google/protobuf/compiler/java/java_extension.h b/src/google/protobuf/compiler/java/java_extension.h
index f1701fb5..bdd42263 100644
--- a/src/google/protobuf/compiler/java/java_extension.h
+++ b/src/google/protobuf/compiler/java/java_extension.h
@@ -67,8 +67,12 @@ class ExtensionGenerator {
virtual ~ExtensionGenerator() {}
virtual void Generate(io::Printer* printer) = 0;
- virtual void GenerateNonNestedInitializationCode(io::Printer* printer) = 0;
- virtual void GenerateRegistrationCode(io::Printer* printer) = 0;
+
+ // Returns an estimate of the number of bytes the printed code will compile to
+ virtual int GenerateNonNestedInitializationCode(io::Printer* printer) = 0;
+
+ // Returns an estimate of the number of bytes the printed code will compile to
+ virtual int GenerateRegistrationCode(io::Printer* printer) = 0;
protected:
static void InitTemplateVars(const FieldDescriptor* descriptor,
@@ -88,8 +92,8 @@ class ImmutableExtensionGenerator : public ExtensionGenerator {
virtual ~ImmutableExtensionGenerator();
virtual void Generate(io::Printer* printer);
- virtual void GenerateNonNestedInitializationCode(io::Printer* printer);
- virtual void GenerateRegistrationCode(io::Printer* printer);
+ virtual int GenerateNonNestedInitializationCode(io::Printer* printer);
+ virtual int GenerateRegistrationCode(io::Printer* printer);
protected:
const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
index af9978e2..3f0fa11f 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -42,12 +42,18 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_enum_field.h>
+#include <google/protobuf/compiler/java/java_enum_field_lite.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/compiler/java/java_lazy_message_field.h>
+#include <google/protobuf/compiler/java/java_lazy_message_field_lite.h>
#include <google/protobuf/compiler/java/java_map_field.h>
+#include <google/protobuf/compiler/java/java_map_field_lite.h>
#include <google/protobuf/compiler/java/java_message_field.h>
+#include <google/protobuf/compiler/java/java_message_field_lite.h>
#include <google/protobuf/compiler/java/java_primitive_field.h>
+#include <google/protobuf/compiler/java/java_primitive_field_lite.h>
#include <google/protobuf/compiler/java/java_string_field.h>
+#include <google/protobuf/compiler/java/java_string_field_lite.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
@@ -133,6 +139,79 @@ ImmutableFieldGenerator* MakeImmutableGenerator(
}
}
+ImmutableFieldLiteGenerator* MakeImmutableLiteGenerator(
+ const FieldDescriptor* field, int messageBitIndex, int builderBitIndex,
+ Context* context) {
+ if (field->is_repeated()) {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_MESSAGE:
+ if (IsMapEntry(field->message_type())) {
+ return new ImmutableMapFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ } else {
+ if (IsLazy(field)) {
+ return new RepeatedImmutableLazyMessageFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ } else {
+ return new RepeatedImmutableMessageFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ }
+ case JAVATYPE_ENUM:
+ return new RepeatedImmutableEnumFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ case JAVATYPE_STRING:
+ return new RepeatedImmutableStringFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ default:
+ return new RepeatedImmutablePrimitiveFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ } else {
+ if (field->containing_oneof()) {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_MESSAGE:
+ if (IsLazy(field)) {
+ return new ImmutableLazyMessageOneofFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ } else {
+ return new ImmutableMessageOneofFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ case JAVATYPE_ENUM:
+ return new ImmutableEnumOneofFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ case JAVATYPE_STRING:
+ return new ImmutableStringOneofFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ default:
+ return new ImmutablePrimitiveOneofFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ } else {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_MESSAGE:
+ if (IsLazy(field)) {
+ return new ImmutableLazyMessageFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ } else {
+ return new ImmutableMessageFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ case JAVATYPE_ENUM:
+ return new ImmutableEnumFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ case JAVATYPE_STRING:
+ return new ImmutableStringFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ default:
+ return new ImmutablePrimitiveFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ }
+ }
+}
+
static inline void ReportUnexpectedPackedFieldsCall(io::Printer* printer) {
// Reaching here indicates a bug. Cases are:
@@ -153,6 +232,13 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const {
ReportUnexpectedPackedFieldsCall(printer);
}
+ImmutableFieldLiteGenerator::~ImmutableFieldLiteGenerator() {}
+
+void ImmutableFieldLiteGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ ReportUnexpectedPackedFieldsCall(printer);
+}
+
// ===================================================================
template <>
@@ -178,6 +264,28 @@ FieldGeneratorMap<ImmutableFieldGenerator>::FieldGeneratorMap(
template<>
FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap() {}
+template <>
+FieldGeneratorMap<ImmutableFieldLiteGenerator>::FieldGeneratorMap(
+ const Descriptor* descriptor, Context* context)
+ : descriptor_(descriptor),
+ field_generators_(new google::protobuf::scoped_ptr<
+ ImmutableFieldLiteGenerator>[descriptor->field_count()]) {
+ // Construct all the FieldGenerators and assign them bit indices for their
+ // bit fields.
+ int messageBitIndex = 0;
+ int builderBitIndex = 0;
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ ImmutableFieldLiteGenerator* generator = MakeImmutableLiteGenerator(
+ descriptor->field(i), messageBitIndex, builderBitIndex, context);
+ field_generators_[i].reset(generator);
+ messageBitIndex += generator->GetNumBitsForMessage();
+ builderBitIndex += generator->GetNumBitsForBuilder();
+ }
+}
+
+template<>
+FieldGeneratorMap<ImmutableFieldLiteGenerator>::~FieldGeneratorMap() {}
+
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
const FieldGeneratorInfo* info,
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index e8d6f3a2..00f3c601 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -93,6 +93,37 @@ class ImmutableFieldGenerator {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldGenerator);
};
+class ImmutableFieldLiteGenerator {
+ public:
+ ImmutableFieldLiteGenerator() {}
+ virtual ~ImmutableFieldLiteGenerator();
+
+ virtual int GetNumBitsForMessage() const = 0;
+ virtual int GetNumBitsForBuilder() const = 0;
+ virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0;
+ virtual void GenerateMembers(io::Printer* printer) const = 0;
+ virtual void GenerateBuilderMembers(io::Printer* printer) const = 0;
+ virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
+ virtual void GenerateMergingCode(io::Printer* printer) const = 0;
+ virtual void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer)
+ const = 0;
+ virtual void GenerateParsingCode(io::Printer* printer) const = 0;
+ virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+ virtual void GenerateParsingDoneCode(io::Printer* printer) const = 0;
+ virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
+ virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
+ virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer)
+ const = 0;
+
+ virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
+ virtual void GenerateHashCode(io::Printer* printer) const = 0;
+
+ virtual string GetBoxedType() const = 0;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldLiteGenerator);
+};
+
// Convenience class which constructs FieldGenerators for a Descriptor.
template<typename FieldGeneratorType>
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index f1e3cf67..68b47ee1 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -38,6 +38,7 @@
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <set>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_enum.h>
@@ -62,6 +63,19 @@ namespace java {
namespace {
+struct FieldDescriptorCompare {
+ bool operator ()(const FieldDescriptor* f1, const FieldDescriptor* f2) {
+ if(f1 == NULL) {
+ return false;
+ }
+ if(f2 == NULL) {
+ return true;
+ }
+ return f1->full_name() < f2->full_name();
+ }
+};
+
+typedef std::set<const FieldDescriptor*, FieldDescriptorCompare> FieldDescriptorSet;
// Recursively searches the given message to collect extensions.
// Returns true if all the extensions can be recognized. The extensions will be
@@ -69,7 +83,7 @@ namespace {
// Returns false when there are unknown fields, in which case the data in the
// extensions output parameter is not reliable and should be discarded.
bool CollectExtensions(const Message& message,
- vector<const FieldDescriptor*>* extensions) {
+ FieldDescriptorSet* extensions) {
const Reflection* reflection = message.GetReflection();
// There are unknown fields that could be extensions, thus this call fails.
@@ -79,7 +93,7 @@ bool CollectExtensions(const Message& message,
reflection->ListFields(message, &fields);
for (int i = 0; i < fields.size(); i++) {
- if (fields[i]->is_extension()) extensions->push_back(fields[i]);
+ if (fields[i]->is_extension()) extensions->insert(fields[i]);
if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) {
if (fields[i]->is_repeated()) {
@@ -106,7 +120,7 @@ bool CollectExtensions(const Message& message,
// in order to handle this case.
void CollectExtensions(const FileDescriptorProto& file_proto,
const DescriptorPool& alternate_pool,
- vector<const FieldDescriptor*>* extensions,
+ FieldDescriptorSet* extensions,
const string& file_data) {
if (!CollectExtensions(file_proto, extensions)) {
// There are unknown fields in the file_proto, which are probably
@@ -139,6 +153,42 @@ void CollectExtensions(const FileDescriptorProto& file_proto,
}
}
+// Compare two field descriptors, returning true if the first should come
+// before the second.
+bool CompareFieldsByName(const FieldDescriptor *a, const FieldDescriptor *b) {
+ return a->full_name() < b->full_name();
+}
+
+// Our static initialization methods can become very, very large.
+// So large that if we aren't careful we end up blowing the JVM's
+// 64K bytes of bytecode/method. Fortunately, since these static
+// methods are executed only once near the beginning of a program,
+// there's usually plenty of stack space available and we can
+// extend our methods by simply chaining them to another method
+// with a tail call. This inserts the sequence call-next-method,
+// end this one, begin-next-method as needed.
+void MaybeRestartJavaMethod(io::Printer* printer,
+ int *bytecode_estimate,
+ int *method_num,
+ const char *chain_statement,
+ const char *method_decl) {
+ // The goal here is to stay under 64K bytes of jvm bytecode/method,
+ // since otherwise we hit a hardcoded limit in the jvm and javac will
+ // then fail with the error "code too large". This limit lets our
+ // estimates be off by a factor of two and still we're okay.
+ static const int bytesPerMethod = 1<<15; // aka 32K
+
+ if ((*bytecode_estimate) > bytesPerMethod) {
+ ++(*method_num);
+ printer->Print(chain_statement, "method_num", SimpleItoa(*method_num));
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print(method_decl, "method_num", SimpleItoa(*method_num));
+ printer->Indent();
+ *bytecode_estimate = 0;
+ }
+}
+
} // namespace
@@ -270,9 +320,16 @@ void FileGenerator::Generate(io::Printer* printer) {
printer->Print(
"static {\n");
printer->Indent();
+ int bytecode_estimate = 0;
+ int method_num = 0;
for (int i = 0; i < file_->message_type_count(); i++) {
- message_generators_[i]->GenerateStaticVariableInitializers(printer);
+ bytecode_estimate += message_generators_[i]->GenerateStaticVariableInitializers(printer);
+ MaybeRestartJavaMethod(
+ printer,
+ &bytecode_estimate, &method_num,
+ "_clinit_autosplit_$method_num$();\n",
+ "private static void _clinit_autosplit_$method_num$() {\n");
}
printer->Outdent();
@@ -303,12 +360,24 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
SharedCodeGenerator shared_code_generator(file_);
shared_code_generator.GenerateDescriptors(printer);
+ int bytecode_estimate = 0;
+ int method_num = 0;
for (int i = 0; i < file_->message_type_count(); i++) {
- message_generators_[i]->GenerateStaticVariableInitializers(printer);
+ bytecode_estimate += message_generators_[i]->GenerateStaticVariableInitializers(printer);
+ MaybeRestartJavaMethod(
+ printer,
+ &bytecode_estimate, &method_num,
+ "_clinit_autosplit_dinit_$method_num$();\n",
+ "private static void _clinit_autosplit_dinit_$method_num$() {\n");
}
for (int i = 0; i < file_->extension_count(); i++) {
- extension_generators_[i]->GenerateNonNestedInitializationCode(printer);
+ bytecode_estimate += extension_generators_[i]->GenerateNonNestedInitializationCode(printer);
+ MaybeRestartJavaMethod(
+ printer,
+ &bytecode_estimate, &method_num,
+ "_clinit_autosplit_dinit_$method_num$();\n",
+ "private static void _clinit_autosplit_dinit_$method_num$() {\n");
}
// Proto compiler builds a DescriptorPool, which holds all the descriptors to
@@ -330,7 +399,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
file_->CopyTo(&file_proto);
string file_data;
file_proto.SerializeToString(&file_data);
- vector<const FieldDescriptor*> extensions;
+ FieldDescriptorSet extensions;
CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
if (extensions.size() > 0) {
@@ -339,10 +408,17 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
printer->Print(
"com.google.protobuf.ExtensionRegistry registry =\n"
" com.google.protobuf.ExtensionRegistry.newInstance();\n");
- for (int i = 0; i < extensions.size(); i++) {
+ FieldDescriptorSet::iterator it;
+ for (it = extensions.begin(); it != extensions.end(); it++) {
google::protobuf::scoped_ptr<ExtensionGenerator> generator(
- generator_factory_->NewExtensionGenerator(extensions[i]));
- generator->GenerateRegistrationCode(printer);
+ generator_factory_->NewExtensionGenerator(*it));
+ bytecode_estimate += generator->GenerateRegistrationCode(printer);
+ MaybeRestartJavaMethod(
+ printer,
+ &bytecode_estimate, &method_num,
+ "_clinit_autosplit_dinit_$method_num$(registry);\n",
+ "private static void _clinit_autosplit_dinit_$method_num$(\n"
+ " com.google.protobuf.ExtensionRegistry registry) {\n");
}
printer->Print(
"com.google.protobuf.Descriptors.FileDescriptor\n"
@@ -394,7 +470,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer*
file_->CopyTo(&file_proto);
string file_data;
file_proto.SerializeToString(&file_data);
- vector<const FieldDescriptor*> extensions;
+ FieldDescriptorSet extensions;
CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
if (extensions.size() > 0) {
diff --git a/src/google/protobuf/compiler/java/java_generator_factory.cc b/src/google/protobuf/compiler/java/java_generator_factory.cc
index 2d1437f0..92ef851b 100644
--- a/src/google/protobuf/compiler/java/java_generator_factory.cc
+++ b/src/google/protobuf/compiler/java/java_generator_factory.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/compiler/java/java_field.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/compiler/java/java_message.h>
+#include <google/protobuf/compiler/java/java_message_lite.h>
#include <google/protobuf/compiler/java/java_service.h>
namespace google {
@@ -57,7 +58,12 @@ ImmutableGeneratorFactory::~ImmutableGeneratorFactory() {}
MessageGenerator* ImmutableGeneratorFactory::NewMessageGenerator(
const Descriptor* descriptor) const {
- return new ImmutableMessageGenerator(descriptor, context_);
+ if (descriptor->file()->options().optimize_for() ==
+ FileOptions::LITE_RUNTIME) {
+ return new ImmutableMessageLiteGenerator(descriptor, context_);
+ } else {
+ return new ImmutableMessageGenerator(descriptor, context_);
+ }
}
ExtensionGenerator* ImmutableGeneratorFactory::NewExtensionGenerator(
diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
index 23685385..e24894b1 100644
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -690,8 +690,8 @@ const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
for (int i = 0; i < descriptor->field_count(); i++) {
fields[i] = descriptor->field(i);
}
- sort(fields, fields + descriptor->field_count(),
- FieldOrderingByNumber());
+ std::sort(fields, fields + descriptor->field_count(),
+ FieldOrderingByNumber());
return fields;
}
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index d957fdc4..96d2545f 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -196,12 +196,6 @@ inline bool HasDescriptorMethods(const FileDescriptor* descriptor) {
FileOptions::LITE_RUNTIME;
}
-inline bool HasNestedBuilders(const Descriptor* descriptor) {
- // The proto-lite version doesn't support nested builders.
- return descriptor->file()->options().optimize_for() !=
- FileOptions::LITE_RUNTIME;
-}
-
// Should we generate generic services for this file?
inline bool HasGenericServices(const FileDescriptor *file) {
return file->service_count() > 0 &&
@@ -297,6 +291,16 @@ struct ExtensionRangeOrdering {
// and return it. The caller should delete the returned array.
const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor);
+// Does this message class have any packed fields?
+inline bool HasPackedFields(const Descriptor* descriptor) {
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ if (descriptor->field(i)->is_packed()) {
+ return true;
+ }
+ }
+ return false;
+}
+
// Check a message type and its sub-message types recursively to see if any of
// them has a required field. Return true if a required field is found.
bool HasRequiredFields(const Descriptor* descriptor);
@@ -320,6 +324,10 @@ inline bool IsMapEntry(const Descriptor* descriptor) {
return descriptor->options().map_entry();
}
+inline bool IsMapField(const FieldDescriptor* descriptor) {
+ return descriptor->is_map();
+}
+
inline bool PreserveUnknownFields(const Descriptor* descriptor) {
return descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
}
diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.cc b/src/google/protobuf/compiler/java/java_lazy_message_field.cc
index 21cab7db..0de8cbe5 100644
--- a/src/google/protobuf/compiler/java/java_lazy_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_lazy_message_field.cc
@@ -72,14 +72,12 @@ GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
" return ($type$) $name$_.getValue($type$.getDefaultInstance());\n"
- "}\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
- " return $name$_;\n"
- "}\n");
- }
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+ " return $name$_;\n"
+ "}\n");
}
void ImmutableLazyMessageFieldGenerator::
@@ -92,14 +90,12 @@ GenerateBuilderMembers(io::Printer* printer) const {
"private com.google.protobuf.LazyFieldLite $name$_ =\n"
" new com.google.protobuf.LazyFieldLite();\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- printer->Print(variables_,
- // If this builder is non-null, it is used and the other fields are
- // ignored.
- "private com.google.protobuf.SingleFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
- "\n");
- }
+ printer->Print(variables_,
+ // If this builder is non-null, it is used and the other fields are
+ // ignored.
+ "private com.google.protobuf.SingleFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
+ "\n");
// The comments above the methods below are based on a hypothetical
// field of type "Field" called "Field".
@@ -179,39 +175,37 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$clear_has_field_bit_builder$;\n"
"return this;\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
- " $set_has_field_bit_builder$;\n"
- " $on_changed$\n"
- " return get$capitalized_name$FieldBuilder().getBuilder();\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
- " if ($name$Builder_ != null) {\n"
- " return $name$Builder_.getMessageOrBuilder();\n"
- " } else {\n"
- " return $name$_;\n"
- " }\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "private com.google.protobuf.SingleFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> \n"
- " get$capitalized_name$FieldBuilder() {\n"
- " if ($name$Builder_ == null) {\n"
- " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder>(\n"
- " $name$_,\n"
- " getParentForChildren(),\n"
- " isClean());\n"
- " $name$_ = null;\n"
- " }\n"
- " return $name$Builder_;\n"
- "}\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
+ " $set_has_field_bit_builder$;\n"
+ " $on_changed$\n"
+ " return get$capitalized_name$FieldBuilder().getBuilder();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+ " if ($name$Builder_ != null) {\n"
+ " return $name$Builder_.getMessageOrBuilder();\n"
+ " } else {\n"
+ " return $name$_;\n"
+ " }\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private com.google.protobuf.SingleFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> \n"
+ " get$capitalized_name$FieldBuilder() {\n"
+ " if ($name$Builder_ == null) {\n"
+ " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder>(\n"
+ " $name$_,\n"
+ " getParentForChildren(),\n"
+ " isClean());\n"
+ " $name$_ = null;\n"
+ " }\n"
+ " return $name$Builder_;\n"
+ "}\n");
}
@@ -243,9 +237,8 @@ GenerateBuildingCode(io::Printer* printer) const {
"}\n");
printer->Print(variables_,
- "result.$name$_.setByteString(\n"
- " $name$_.toByteString(),\n"
- " $name$_.getExtensionRegistry());\n");
+ "result.$name$_.set(\n"
+ " $name$_);\n");
}
void ImmutableLazyMessageFieldGenerator::
@@ -425,9 +418,8 @@ GenerateBuildingCode(io::Printer* printer) const {
printer->Print(variables_,
"result.$oneof_name$_ = new $lazy_type$();\n"
- "(($lazy_type$) result.$oneof_name$_).setByteString(\n"
- " (($lazy_type$) $oneof_name$_).toByteString(),\n"
- " (($lazy_type$) $oneof_name$_).getExtensionRegistry());\n");
+ "(($lazy_type$) result.$oneof_name$_).set(\n"
+ " (($lazy_type$) $oneof_name$_));\n");
printer->Outdent();
printer->Print("}\n");
}
@@ -540,14 +532,12 @@ GenerateBuilderMembers(io::Printer* printer) const {
"}\n"
"\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- printer->Print(variables_,
- // If this builder is non-null, it is used and the other fields are
- // ignored.
- "private com.google.protobuf.RepeatedFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
- "\n");
- }
+ printer->Print(variables_,
+ // If this builder is non-null, it is used and the other fields are
+ // ignored.
+ "private com.google.protobuf.RepeatedFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
+ "\n");
// The comments above the methods below are based on a hypothetical
// repeated field of type "Field" called "RepeatedField".
@@ -725,70 +715,68 @@ GenerateBuilderMembers(io::Printer* printer) const {
"return this;\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
- " int index) {\n"
- " return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
- "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
+ " int index) {\n"
+ " return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
+ "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
- " int index) {\n"
- " if ($name$Builder_ == null) {\n"
- " return $name$_.get(index);"
- " } else {\n"
- " return $name$Builder_.getMessageOrBuilder(index);\n"
- " }\n"
- "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+ " int index) {\n"
+ " if ($name$Builder_ == null) {\n"
+ " return $name$_.get(index);"
+ " } else {\n"
+ " return $name$Builder_.getMessageOrBuilder(index);\n"
+ " }\n"
+ "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
- " get$capitalized_name$OrBuilderList() {\n"
- " if ($name$Builder_ != null) {\n"
- " return $name$Builder_.getMessageOrBuilderList();\n"
- " } else {\n"
- " return java.util.Collections.unmodifiableList($name$_);\n"
- " }\n"
- "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+ " get$capitalized_name$OrBuilderList() {\n"
+ " if ($name$Builder_ != null) {\n"
+ " return $name$Builder_.getMessageOrBuilderList();\n"
+ " } else {\n"
+ " return java.util.Collections.unmodifiableList($name$_);\n"
+ " }\n"
+ "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
- " return get$capitalized_name$FieldBuilder().addBuilder(\n"
- " $type$.getDefaultInstance());\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
- " int index) {\n"
- " return get$capitalized_name$FieldBuilder().addBuilder(\n"
- " index, $type$.getDefaultInstance());\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public java.util.List<$type$.Builder> \n"
- " get$capitalized_name$BuilderList() {\n"
- " return get$capitalized_name$FieldBuilder().getBuilderList();\n"
- "}\n"
- "private com.google.protobuf.RepeatedFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> \n"
- " get$capitalized_name$FieldBuilder() {\n"
- " if ($name$Builder_ == null) {\n"
- " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder>(\n"
- " $name$_,\n"
- " $get_mutable_bit_builder$,\n"
- " getParentForChildren(),\n"
- " isClean());\n"
- " $name$_ = null;\n"
- " }\n"
- " return $name$Builder_;\n"
- "}\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
+ " return get$capitalized_name$FieldBuilder().addBuilder(\n"
+ " $type$.getDefaultInstance());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
+ " int index) {\n"
+ " return get$capitalized_name$FieldBuilder().addBuilder(\n"
+ " index, $type$.getDefaultInstance());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$type$.Builder> \n"
+ " get$capitalized_name$BuilderList() {\n"
+ " return get$capitalized_name$FieldBuilder().getBuilderList();\n"
+ "}\n"
+ "private com.google.protobuf.RepeatedFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> \n"
+ " get$capitalized_name$FieldBuilder() {\n"
+ " if ($name$Builder_ == null) {\n"
+ " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder>(\n"
+ " $name$_,\n"
+ " $get_mutable_bit_builder$,\n"
+ " getParentForChildren(),\n"
+ " isClean());\n"
+ " $name$_ = null;\n"
+ " }\n"
+ " return $name$Builder_;\n"
+ "}\n");
}
void RepeatedImmutableLazyMessageFieldGenerator::
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
new file mode 100644
index 00000000..283ba1d3
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
@@ -0,0 +1,708 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: niwasaki@google.com (Naoki Iwasaki)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_lazy_message_field_lite.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+ImmutableLazyMessageFieldLiteGenerator::
+ImmutableLazyMessageFieldLiteGenerator(
+ const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : ImmutableMessageFieldLiteGenerator(
+ descriptor, messageBitIndex, builderBitIndex, context) {
+}
+
+ImmutableLazyMessageFieldLiteGenerator::
+~ImmutableLazyMessageFieldLiteGenerator() {}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private com.google.protobuf.LazyFieldLite $name$_ =\n"
+ " new com.google.protobuf.LazyFieldLite();\n");
+
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return ($type$) $name$_.getValue($type$.getDefaultInstance());\n"
+ "}\n");
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " $name$_.setValue(value);\n"
+ " $set_has_field_bit_message$;\n"
+ "}\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " $name$_.setValue(builderForValue.build());\n"
+ " $set_has_field_bit_message$;\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void merge$capitalized_name$($type$ value) {\n"
+ " if ($get_has_field_bit_message$ &&\n"
+ " !$name$_.containsDefaultInstance()) {\n"
+ " $name$_.setValue(\n"
+ " $type$.newBuilder(\n"
+ " get$capitalized_name$()).mergeFrom(value).buildPartial());\n"
+ " } else {\n"
+ " $name$_.setValue(value);\n"
+ " }\n"
+ " $set_has_field_bit_message$;\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $name$_.clear();\n"
+ " $clear_has_field_bit_message$;\n"
+ "}\n");
+}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ // The comments above the methods below are based on a hypothetical
+ // field of type "Field" called "Field".
+
+ // boolean hasField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.merge$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_.clear();\n");
+}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateMergingCode(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");
+}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_.setByteString(input.readBytes(), extensionRegistry);\n");
+ printer->Print(variables_,
+ "$set_has_field_bit_message$;\n");
+}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ // Do not de-serialize lazy fields.
+ printer->Print(variables_,
+ "if ($get_has_field_bit_message$) {\n"
+ " output.writeBytes($number$, $name$_.toByteString());\n"
+ "}\n");
+}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($get_has_field_bit_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeLazyFieldSize($number$, $name$_);\n"
+ "}\n");
+}
+
+// ===================================================================
+
+ImmutableLazyMessageOneofFieldLiteGenerator::
+ImmutableLazyMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : ImmutableLazyMessageFieldLiteGenerator(
+ descriptor, messageBitIndex, builderBitIndex, context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+ variables_["lazy_type"] = "com.google.protobuf.LazyFieldLite";
+}
+
+ImmutableLazyMessageOneofFieldLiteGenerator::
+~ImmutableLazyMessageOneofFieldLiteGenerator() {}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldDocComment(printer, descriptor_);
+
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n"
+ " $type$.getDefaultInstance());\n"
+ " }\n"
+ " return $type$.getDefaultInstance();\n"
+ "}\n");
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " if (!($has_oneof_case_message$)) {\n"
+ " $oneof_name$_ = new $lazy_type$();\n"
+ " $set_oneof_case_message$;\n"
+ " }\n"
+ " (($lazy_type$) $oneof_name$_).setValue(value);\n"
+ "}\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " if (!($has_oneof_case_message$)) {\n"
+ " $oneof_name$_ = new $lazy_type$();\n"
+ " $set_oneof_case_message$;\n"
+ " }\n"
+ " (($lazy_type$) $oneof_name$_).setValue(builderForValue.build());\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void merge$capitalized_name$($type$ value) {\n"
+ " if ($has_oneof_case_message$ &&\n"
+ " !(($lazy_type$) $oneof_name$_).containsDefaultInstance()) {\n"
+ " (($lazy_type$) $oneof_name$_).setValue(\n"
+ " $type$.newBuilder(\n"
+ " get$capitalized_name$()).mergeFrom(value).buildPartial());\n"
+ " } else {\n"
+ " if (!($has_oneof_case_message$)) {\n"
+ " $oneof_name$_ = new $lazy_type$();\n"
+ " $set_oneof_case_message$;\n"
+ " }\n"
+ " (($lazy_type$) $oneof_name$_).setValue(value);\n"
+ " }\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ "}\n");
+}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ // boolean hasField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.merge$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateMergingCode(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");
+}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!($has_oneof_case_message$)) {\n"
+ " $oneof_name$_ = new $lazy_type$();\n"
+ "}\n"
+ "(($lazy_type$) $oneof_name$_).setByteString(\n"
+ " input.readBytes(), extensionRegistry);\n"
+ "$set_oneof_case_message$;\n");
+}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ // Do not de-serialize lazy fields.
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " output.writeBytes(\n"
+ " $number$, (($lazy_type$) $oneof_name$_).toByteString());\n"
+ "}\n");
+}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeLazyFieldSize($number$, ($lazy_type$) $oneof_name$_);\n"
+ "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutableLazyMessageFieldLiteGenerator::
+RepeatedImmutableLazyMessageFieldLiteGenerator(
+ const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : RepeatedImmutableMessageFieldLiteGenerator(
+ descriptor, messageBitIndex, builderBitIndex, context) {
+}
+
+
+RepeatedImmutableLazyMessageFieldLiteGenerator::
+~RepeatedImmutableLazyMessageFieldLiteGenerator() {}
+
+void RepeatedImmutableLazyMessageFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private com.google.protobuf.Internal.ProtobufList<\n"
+ " com.google.protobuf.LazyFieldLite> $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$type$>\n"
+ " get$capitalized_name$List() {\n"
+ " java.util.List<$type$> list =\n"
+ " new java.util.ArrayList<$type$>($name$_.size());\n"
+ " for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n"
+ " list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n"
+ " }\n"
+ // TODO(dweis): Make this list immutable?
+ " return list;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<? extends $type$OrBuilder>\n"
+ " get$capitalized_name$OrBuilderList() {\n"
+ " return get$capitalized_name$List();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+ " return ($type$)\n"
+ " $name$_.get(index).getValue($type$.getDefaultInstance());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+ " int index) {\n"
+ " return ($type$OrBuilder)\n"
+ " $name$_.get(index).getValue($type$.getDefaultInstance());\n"
+ "}\n");
+
+ printer->Print(variables_,
+ "private void ensure$capitalized_name$IsMutable() {\n"
+ " if (!$is_mutable$) {\n"
+ " $name$_ = newProtobufList($name$_);\n"
+ " }\n"
+ "}\n"
+ "\n");
+
+ // Builder setRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(\n"
+ " index, com.google.protobuf.LazyFieldLite.fromValue(value));\n"
+ "}\n");
+
+ // Builder setRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(\n"
+ " builderForValue.build()));\n"
+ "}\n");
+
+ // Builder addRepeatedField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(value));\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(\n"
+ " index, com.google.protobuf.LazyFieldLite.fromValue(value));\n"
+ "}\n");
+
+ // Builder addRepeatedField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(\n"
+ " builderForValue.build()));\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(\n"
+ " builderForValue.build()));\n"
+ "}\n");
+
+ // Builder addAllRepeatedField(Iterable<Field> values)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " for (com.google.protobuf.MessageLite v : values) {\n"
+ " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(v));\n"
+ " }\n"
+ "}\n");
+
+ // Builder clearAllRepeatedField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $name$_ = emptyProtobufList();\n"
+ "}\n");
+
+ // Builder removeRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void remove$capitalized_name$(int index) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.remove(index);\n"
+ "}\n");
+}
+
+void RepeatedImmutableLazyMessageFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ // List<Field> getRepeatedFieldList()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+ " return java.util.Collections.unmodifiableList(\n"
+ " instance.get$capitalized_name$List());\n"
+ "}\n");
+
+ // int getRepeatedFieldCount()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return instance.get$capitalized_name$Count();\n"
+ "}\n");
+
+ // Field getRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+ " return instance.get$capitalized_name$(index);\n"
+ "}\n");
+
+ // Builder setRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder setRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addRepeatedField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addRepeatedField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(index, builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addAllRepeatedField(Iterable<Field> values)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$(values);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder clearAllRepeatedField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder removeRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder remove$capitalized_name$(int index) {\n"
+ " copyOnWrite();\n"
+ " instance.remove$capitalized_name$(index);\n"
+ " return this;\n"
+ "}\n");
+}
+
+void RepeatedImmutableLazyMessageFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!$is_mutable$) {\n"
+ " $name$_ = newProtobufList();\n"
+ "}\n"
+ "$name$_.add(new com.google.protobuf.LazyFieldLite(\n"
+ " extensionRegistry, input.readBytes()));\n");
+}
+
+void RepeatedImmutableLazyMessageFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.writeBytes($number$, $name$_.get(i).toByteString());\n"
+ "}\n");
+}
+
+void RepeatedImmutableLazyMessageFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeLazyFieldSize($number$, $name$_.get(i));\n"
+ "}\n");
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
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
new file mode 100644
index 00000000..e85ec0f3
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h
@@ -0,0 +1,118 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: niwasaki@google.com (Naoki Iwasaki)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__
+
+#include <google/protobuf/compiler/java/java_field.h>
+#include <google/protobuf/compiler/java/java_message_field_lite.h>
+
+namespace google {
+namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ }
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableLazyMessageFieldLiteGenerator
+ : public ImmutableMessageFieldLiteGenerator {
+ public:
+ explicit ImmutableLazyMessageFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableLazyMessageFieldLiteGenerator();
+
+ // overroads ImmutableMessageFieldLiteGenerator ------------------------------
+ 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 GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageFieldLiteGenerator);
+};
+
+class ImmutableLazyMessageOneofFieldLiteGenerator
+ : public ImmutableLazyMessageFieldLiteGenerator {
+ public:
+ ImmutableLazyMessageOneofFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableLazyMessageOneofFieldLiteGenerator();
+
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutableLazyMessageFieldLiteGenerator
+ : public RepeatedImmutableMessageFieldLiteGenerator {
+ public:
+ explicit RepeatedImmutableLazyMessageFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~RepeatedImmutableLazyMessageFieldLiteGenerator();
+
+ // overroads RepeatedImmutableMessageFieldLiteGenerator ----------------------
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableLazyMessageFieldLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc
index 2986f51f..44b86cd7 100644
--- a/src/google/protobuf/compiler/java/java_map_field.cc
+++ b/src/google/protobuf/compiler/java/java_map_field.cc
@@ -133,9 +133,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
(*variables)["set_mutable_bit_parser"] =
GenerateSetBitMutableLocal(builderBitIndex);
+ (*variables)["default_entry"] = (*variables)["capitalized_name"] +
+ "DefaultEntryHolder.defaultEntry";
if (HasDescriptorMethods(descriptor->file())) {
(*variables)["lite"] = "";
- (*variables)["map_field_parameter"] = (*variables)["name"] + "DefaultEntry";
+ (*variables)["map_field_parameter"] = (*variables)["default_entry"];
(*variables)["descriptor"] =
name_resolver->GetImmutableClassName(descriptor->file()) +
".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) +
@@ -154,9 +156,7 @@ ImmutableMapFieldGenerator(const FieldDescriptor* descriptor,
int messageBitIndex,
int builderBitIndex,
Context* context)
- : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
- builderBitIndex_(builderBitIndex), context_(context),
- name_resolver_(context->GetNameResolver()) {
+ : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
context->GetFieldGeneratorInfo(descriptor),
name_resolver_, &variables_);
@@ -201,22 +201,29 @@ void ImmutableMapFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(
variables_,
- "private static final com.google.protobuf.MapEntry$lite$<\n"
- " $type_parameters$> $name$DefaultEntry =\n"
- " com.google.protobuf.MapEntry$lite$\n"
- " .<$type_parameters$>newDefaultInstance(\n"
- " $descriptor$\n"
- " $key_wire_type$,\n"
- " $key_default_value$,\n"
- " $value_wire_type$,\n"
- " $value_default_value$);\n");
+ "private static final class $capitalized_name$DefaultEntryHolder {\n"
+ " static final com.google.protobuf.MapEntry$lite$<\n"
+ " $type_parameters$> defaultEntry =\n"
+ " com.google.protobuf.MapEntry$lite$\n"
+ " .<$type_parameters$>newDefaultInstance(\n"
+ " $descriptor$\n"
+ " $key_wire_type$,\n"
+ " $key_default_value$,\n"
+ " $value_wire_type$,\n"
+ " $value_default_value$);\n"
+ "}\n");
printer->Print(
variables_,
"private com.google.protobuf.MapField$lite$<\n"
- " $type_parameters$> $name$_ =\n"
- " com.google.protobuf.MapField$lite$.emptyMapField(\n"
- " $map_field_parameter$);\n"
- "\n");
+ " $type_parameters$> $name$_;\n"
+ "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+ "internalGet$capitalized_name$() {\n"
+ " if ($name$_ == null) {\n"
+ " return com.google.protobuf.MapField$lite$.emptyMapField(\n"
+ " $map_field_parameter$);\n"
+ " }\n"
+ " return $name$_;\n"
+ "}\n");
if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
printer->Print(
variables_,
@@ -233,7 +240,7 @@ GenerateMembers(io::Printer* printer) const {
"$deprecation$\n"
"public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
"get$capitalized_name$Value() {\n"
- " return $name$_.getMap();\n"
+ " return internalGet$capitalized_name$().getMap();\n"
"}\n");
}
WriteFieldDocComment(printer, descriptor_);
@@ -244,7 +251,8 @@ GenerateMembers(io::Printer* printer) const {
"get$capitalized_name$() {\n"
" return new com.google.protobuf.Internal.MapAdapter<\n"
" $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
- " $name$_.getMap(), $name$ValueConverter);\n"
+ " internalGet$capitalized_name$().getMap(),\n"
+ " $name$ValueConverter);\n"
"}\n");
} else {
WriteFieldDocComment(printer, descriptor_);
@@ -252,7 +260,7 @@ GenerateMembers(io::Printer* printer) const {
variables_,
"$deprecation$\n"
"public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
- " return $name$_.getMap();\n"
+ " return internalGet$capitalized_name$().getMap();\n"
"}\n");
}
}
@@ -262,10 +270,27 @@ GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(
variables_,
"private com.google.protobuf.MapField$lite$<\n"
- " $type_parameters$> $name$_ =\n"
- " com.google.protobuf.MapField$lite$.newMapField(\n"
- " $map_field_parameter$);\n"
- "\n");
+ " $type_parameters$> $name$_;\n"
+ "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+ "internalGet$capitalized_name$() {\n"
+ " if ($name$_ == null) {\n"
+ " return com.google.protobuf.MapField$lite$.emptyMapField(\n"
+ " $map_field_parameter$);\n"
+ " }\n"
+ " return $name$_;\n"
+ "}\n"
+ "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+ "internalGetMutable$capitalized_name$() {\n"
+ " $on_changed$;\n"
+ " if ($name$_ == null) {\n"
+ " $name$_ = com.google.protobuf.MapField$lite$.newMapField(\n"
+ " $map_field_parameter$);\n"
+ " }\n"
+ " if (!$name$_.isMutable()) {\n"
+ " $name$_ = $name$_.copy();\n"
+ " }\n"
+ " return $name$_;\n"
+ "}\n");
if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
WriteFieldDocComment(printer, descriptor_);
printer->Print(
@@ -275,7 +300,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
"get$capitalized_name$() {\n"
" return new com.google.protobuf.Internal.MapAdapter<\n"
" $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
- " $name$_.getMap(), $name$ValueConverter);\n"
+ " internalGet$capitalized_name$().getMap(),\n"
+ " $name$ValueConverter);\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
@@ -283,10 +309,10 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$deprecation$\n"
"public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
"getMutable$capitalized_name$() {\n"
- " $on_changed$\n"
" return new com.google.protobuf.Internal.MapAdapter<\n"
" $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
- " $name$_.getMutableMap(), $name$ValueConverter);\n"
+ " internalGetMutable$capitalized_name$().getMutableMap(),\n"
+ " $name$ValueConverter);\n"
"}\n");
if (SupportUnknownEnumValue(descriptor_->file())) {
WriteFieldDocComment(printer, descriptor_);
@@ -295,7 +321,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$deprecation$\n"
"public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
"get$capitalized_name$Value() {\n"
- " return $name$_.getMap();\n"
+ " return internalGet$capitalized_name$().getMap();\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
@@ -303,8 +329,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$deprecation$\n"
"public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
"getMutable$capitalized_name$Value() {\n"
- " $on_changed$\n"
- " return $name$_.getMutableMap();\n"
+ " return internalGetMutable$capitalized_name$().getMutableMap();\n"
"}\n");
}
} else {
@@ -312,15 +337,14 @@ GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(
variables_,
"public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
- " return $name$_.getMap();\n"
+ " return internalGet$capitalized_name$().getMap();\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
variables_,
"public java.util.Map<$type_parameters$>\n"
"getMutable$capitalized_name$() {\n"
- " $on_changed$\n"
- " return $name$_.getMutableMap();\n"
+ " return internalGetMutable$capitalized_name$().getMutableMap();\n"
"}\n");
}
}
@@ -339,24 +363,23 @@ void ImmutableMapFieldGenerator::
GenerateBuilderClearCode(io::Printer* printer) const {
printer->Print(
variables_,
- "$name$_.clear();\n");
+ "internalGetMutable$capitalized_name$().clear();\n");
}
void ImmutableMapFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(
variables_,
- "$name$_.mergeFrom(other.$name$_);\n");
+ "internalGetMutable$capitalized_name$().mergeFrom(\n"
+ " other.internalGet$capitalized_name$());\n");
}
void ImmutableMapFieldGenerator::
GenerateBuildingCode(io::Printer* printer) const {
printer->Print(
variables_,
- // We do a copy of the map field to ensure that the built result is
- // immutable. Implementation of this copy() method can do copy-on-write
- // to defer this copy until further modifications are made on the field.
- "result.$name$_ = $name$_.copy();\n");
+ "result.$name$_ = internalGet$capitalized_name$();\n"
+ "result.$name$_.makeImmutable();\n");
}
void ImmutableMapFieldGenerator::
@@ -374,7 +397,7 @@ GenerateParsingCode(io::Printer* printer) const {
variables_,
"com.google.protobuf.ByteString bytes = input.readBytes();\n"
"com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
- "$name$ = $name$DefaultEntry.getParserForType().parseFrom(bytes);\n");
+ "$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n");
printer->Print(
variables_,
"if ($value_enum_type$.valueOf($name$.getValue()) == null) {\n"
@@ -387,7 +410,7 @@ GenerateParsingCode(io::Printer* printer) const {
variables_,
"com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
"$name$ = input.readMessage(\n"
- " $name$DefaultEntry.getParserForType(), extensionRegistry);\n"
+ " $default_entry$.getParserForType(), extensionRegistry);\n"
"$name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n");
}
}
@@ -402,9 +425,9 @@ GenerateSerializationCode(io::Printer* printer) const {
printer->Print(
variables_,
"for (java.util.Map.Entry<$type_parameters$> entry\n"
- " : $name$_.getMap().entrySet()) {\n"
+ " : internalGet$capitalized_name$().getMap().entrySet()) {\n"
" com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
- " $name$ = $name$DefaultEntry.newBuilderForType()\n"
+ " $name$ = $default_entry$.newBuilderForType()\n"
" .setKey(entry.getKey())\n"
" .setValue(entry.getValue())\n"
" .build();\n"
@@ -417,9 +440,9 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(
variables_,
"for (java.util.Map.Entry<$type_parameters$> entry\n"
- " : $name$_.getMap().entrySet()) {\n"
+ " : internalGet$capitalized_name$().getMap().entrySet()) {\n"
" com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
- " $name$ = $name$DefaultEntry.newBuilderForType()\n"
+ " $name$ = $default_entry$.newBuilderForType()\n"
" .setKey(entry.getKey())\n"
" .setValue(entry.getValue())\n"
" .build();\n"
@@ -432,16 +455,17 @@ void ImmutableMapFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(
variables_,
- "result = result && $name$_.equals(other.$name$_);\n");
+ "result = result && internalGet$capitalized_name$().equals(\n"
+ " other.internalGet$capitalized_name$());\n");
}
void ImmutableMapFieldGenerator::
GenerateHashCode(io::Printer* printer) const {
printer->Print(
variables_,
- "if (!$name$_.getMap().isEmpty()) {\n"
+ "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n"
" hash = (37 * hash) + $constant_name$;\n"
- " hash = (53 * hash) + $name$_.hashCode();\n"
+ " hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h
index 80a94f45..f2768f3a 100644
--- a/src/google/protobuf/compiler/java/java_map_field.h
+++ b/src/google/protobuf/compiler/java/java_map_field.h
@@ -68,9 +68,6 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator {
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
- const int messageBitIndex_;
- const int builderBitIndex_;
- Context* context_;
ClassNameResolver* name_resolver_;
};
diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc
new file mode 100644
index 00000000..cd1698f0
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc
@@ -0,0 +1,459 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/java/java_map_field_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>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) {
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+ const Descriptor* message = descriptor->message_type();
+ GOOGLE_CHECK(message->options().map_entry());
+ return message->FindFieldByName("key");
+}
+
+const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) {
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+ const Descriptor* message = descriptor->message_type();
+ GOOGLE_CHECK(message->options().map_entry());
+ return message->FindFieldByName("value");
+}
+
+string TypeName(const FieldDescriptor* field,
+ ClassNameResolver* name_resolver,
+ bool boxed) {
+ if (GetJavaType(field) == JAVATYPE_MESSAGE) {
+ return name_resolver->GetImmutableClassName(field->message_type());
+ } else if (GetJavaType(field) == JAVATYPE_ENUM) {
+ return name_resolver->GetImmutableClassName(field->enum_type());
+ } else {
+ return boxed ? BoxedPrimitiveTypeName(GetJavaType(field))
+ : PrimitiveTypeName(GetJavaType(field));
+ }
+}
+
+string WireType(const FieldDescriptor* field) {
+ return "com.google.protobuf.WireFormat.FieldType." +
+ string(FieldTypeName(field->type()));
+}
+
+void SetMessageVariables(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ map<string, string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+
+ (*variables)["type"] =
+ name_resolver->GetImmutableClassName(descriptor->message_type());
+ const FieldDescriptor* key = KeyField(descriptor);
+ const FieldDescriptor* value = ValueField(descriptor);
+ (*variables)["key_type"] = TypeName(key, name_resolver, false);
+ (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true);
+ (*variables)["key_wire_type"] = WireType(key);
+ (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
+ if (GetJavaType(value) == JAVATYPE_ENUM) {
+ // We store enums as Integers internally.
+ (*variables)["value_type"] = "int";
+ (*variables)["boxed_value_type"] = "java.lang.Integer";
+ (*variables)["value_wire_type"] = WireType(value);
+ (*variables)["value_default_value"] =
+ DefaultValue(value, true, name_resolver) + ".getNumber()";
+
+ (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);
+
+ if (SupportUnknownEnumValue(descriptor->file())) {
+ // Map unknown values to a special UNRECOGNIZED value if supported.
+ (*variables)["unrecognized_value"] =
+ (*variables)["value_enum_type"] + ".UNRECOGNIZED";
+ } else {
+ // Map unknown values to the default value if we don't have UNRECOGNIZED.
+ (*variables)["unrecognized_value"] =
+ DefaultValue(value, true, name_resolver);
+ }
+ } else {
+ (*variables)["value_type"] = TypeName(value, name_resolver, false);
+ (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
+ (*variables)["value_wire_type"] = WireType(value);
+ (*variables)["value_default_value"] =
+ DefaultValue(value, true, name_resolver);
+ }
+ (*variables)["type_parameters"] =
+ (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] = descriptor->options().deprecated()
+ ? "@java.lang.Deprecated " : "";
+ (*variables)["on_changed"] =
+ HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+ (*variables)["default_entry"] = (*variables)["capitalized_name"] +
+ "DefaultEntryHolder.defaultEntry";
+ (*variables)["lite"] = "Lite";
+ (*variables)["descriptor"] = "";
+}
+
+} // namespace
+
+ImmutableMapFieldLiteGenerator::
+ImmutableMapFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+ SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+ImmutableMapFieldLiteGenerator::
+~ImmutableMapFieldLiteGenerator() {}
+
+int ImmutableMapFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+int ImmutableMapFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "get$capitalized_name$();\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$java.util.Map<$type_parameters$>\n"
+ "get$capitalized_name$Value();\n");
+ }
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$java.util.Map<$type_parameters$>\n"
+ "get$capitalized_name$();\n");
+ }
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "private static final class $capitalized_name$DefaultEntryHolder {\n"
+ " static final com.google.protobuf.MapEntry$lite$<\n"
+ " $type_parameters$> defaultEntry =\n"
+ " com.google.protobuf.MapEntry$lite$\n"
+ " .<$type_parameters$>newDefaultInstance(\n"
+ " $descriptor$\n"
+ " $key_wire_type$,\n"
+ " $key_default_value$,\n"
+ " $value_wire_type$,\n"
+ " $value_default_value$);\n"
+ "}\n");
+ printer->Print(
+ variables_,
+ "private com.google.protobuf.MapField$lite$<\n"
+ " $type_parameters$> $name$_ =\n"
+ " com.google.protobuf.MapField$lite$.emptyMapField();\n"
+ "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+ "internalGet$capitalized_name$() {\n"
+ " return $name$_;\n"
+ "}\n"
+ "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+ "internalGetMutable$capitalized_name$() {\n"
+ " if (!$name$_.isMutable()) {\n"
+ " $name$_ = $name$_.copy();\n"
+ " }\n"
+ " return $name$_;\n"
+ "}\n");
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ printer->Print(
+ variables_,
+ "private static final\n"
+ "com.google.protobuf.Internal.MapAdapter.Converter<\n"
+ " java.lang.Integer, $value_enum_type$> $name$ValueConverter =\n"
+ " com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
+ " $value_enum_type$.internalGetValueMap(),\n"
+ " $unrecognized_value$);\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "get$capitalized_name$Value() {\n"
+ " return internalGet$capitalized_name$().getMap();\n"
+ "}\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "get$capitalized_name$() {\n"
+ " return new com.google.protobuf.Internal.MapAdapter<\n"
+ " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+ " internalGet$capitalized_name$().getMap(),\n"
+ " $name$ValueConverter);\n"
+ "}\n");
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
+ " return internalGet$capitalized_name$().getMap();\n"
+ "}\n");
+ }
+
+ // Generate private setters for the builder to proxy into.
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "private java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "getMutable$capitalized_name$() {\n"
+ " return new com.google.protobuf.Internal.MapAdapter<\n"
+ " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+ " internalGetMutable$capitalized_name$().getMutableMap(),\n"
+ " $name$ValueConverter);\n"
+ "}\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "private java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "getMutable$capitalized_name$Value() {\n"
+ " return internalGetMutable$capitalized_name$().getMutableMap();\n"
+ "}\n");
+ }
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "private java.util.Map<$type_parameters$>\n"
+ "getMutable$capitalized_name$() {\n"
+ " return internalGetMutable$capitalized_name$().getMutableMap();\n"
+ "}\n");
+ }
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "getMutable$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " return instance.getMutable$capitalized_name$();\n"
+ "}\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "get$capitalized_name$Value() {\n"
+ " return instance.get$capitalized_name$Value();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "getMutable$capitalized_name$Value() {\n"
+ " copyOnWrite();\n"
+ " return instance.getMutable$capitalized_name$Value();\n"
+ "}\n");
+ }
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "public java.util.Map<$type_parameters$>\n"
+ "getMutable$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " return instance.getMutable$capitalized_name$();\n"
+ "}\n");
+ }
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // Nothing to initialize.
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ // Nothing to initialize.
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "internalGetMutable$capitalized_name$().mergeFrom(\n"
+ " other.internalGet$capitalized_name$());\n");
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_.makeImmutable();\n");
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if (!$name$_.isMutable()) {\n"
+ " $name$_ = $name$_.copy();\n"
+ "}\n");
+ if (!SupportUnknownEnumValue(descriptor_->file()) &&
+ GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ printer->Print(
+ variables_,
+ "com.google.protobuf.ByteString bytes = input.readBytes();\n"
+ "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+ "$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n");
+ printer->Print(
+ variables_,
+ "if ($value_enum_type$.valueOf($name$.getValue()) == null) {\n"
+ " unknownFields.mergeLengthDelimitedField($number$, bytes);\n"
+ "} else {\n"
+ " $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
+ "}\n");
+ } else {
+ printer->Print(
+ variables_,
+ "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+ "$name$ = input.readMessage(\n"
+ " $default_entry$.getParserForType(), extensionRegistry);\n"
+ "$name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n");
+ }
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ // Nothing to do here.
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "for (java.util.Map.Entry<$type_parameters$> entry\n"
+ " : internalGet$capitalized_name$().getMap().entrySet()) {\n"
+ " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+ " $name$ = $default_entry$.newBuilderForType()\n"
+ " .setKey(entry.getKey())\n"
+ " .setValue(entry.getValue())\n"
+ " .build();\n"
+ " output.writeMessage($number$, $name$);\n"
+ "}\n");
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "for (java.util.Map.Entry<$type_parameters$> entry\n"
+ " : internalGet$capitalized_name$().getMap().entrySet()) {\n"
+ " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+ " $name$ = $default_entry$.newBuilderForType()\n"
+ " .setKey(entry.getKey())\n"
+ " .setValue(entry.getValue())\n"
+ " .build();\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeMessageSize($number$, $name$);\n"
+ "}\n");
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "result = result && internalGet$capitalized_name$().equals(\n"
+ " other.internalGet$capitalized_name$());\n");
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n"
+ "}\n");
+}
+
+string ImmutableMapFieldLiteGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.h b/src/google/protobuf/compiler/java/java_map_field_lite.h
new file mode 100644
index 00000000..a09cd536
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.h
@@ -0,0 +1,78 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__
+
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMapFieldLiteGenerator : public ImmutableFieldLiteGenerator {
+ public:
+ explicit ImmutableMapFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableMapFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ int GetNumBitsForMessage() const;
+ int GetNumBitsForBuilder() const;
+ void GenerateInterfaceMembers(io::Printer* printer) const;
+ 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 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ ClassNameResolver* name_resolver_;
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 1171b718..09b0fd94 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -49,6 +49,8 @@
#include <google/protobuf/compiler/java/java_extension.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>
+#include <google/protobuf/compiler/java/java_message_builder_lite.h>
#include <google/protobuf/compiler/java/java_name_resolver.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/printer.h>
@@ -93,44 +95,47 @@ ImmutableMessageGenerator::ImmutableMessageGenerator(
: MessageGenerator(descriptor), context_(context),
name_resolver_(context->GetNameResolver()),
field_generators_(descriptor, context_) {
+ GOOGLE_CHECK_NE(
+ FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
}
ImmutableMessageGenerator::~ImmutableMessageGenerator() {}
void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) {
- if (HasDescriptorMethods(descriptor_)) {
- // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
- // used in the construction of descriptors, we have a tricky bootstrapping
- // problem. To help control static initialization order, we make sure all
- // descriptors and other static data that depends on them are members of
- // the outermost class in the file. This way, they will be initialized in
- // a deterministic order.
-
- map<string, string> vars;
- vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
- vars["index"] = SimpleItoa(descriptor_->index());
- vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
- if (descriptor_->containing_type() != NULL) {
- vars["parent"] = UniqueFileScopeIdentifier(
- descriptor_->containing_type());
- }
- if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
- // We can only make these package-private since the classes that use them
- // are in separate files.
- vars["private"] = "";
- } else {
- vars["private"] = "private ";
- }
+ // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
+ // used in the construction of descriptors, we have a tricky bootstrapping
+ // problem. To help control static initialization order, we make sure all
+ // descriptors and other static data that depends on them are members of
+ // the outermost class in the file. This way, they will be initialized in
+ // a deterministic order.
- // The descriptor for this type.
- printer->Print(vars,
- "$private$static final com.google.protobuf.Descriptors.Descriptor\n"
- " internal_$identifier$_descriptor;\n");
-
- // And the FieldAccessorTable.
- GenerateFieldAccessorTable(printer);
+ map<string, string> vars;
+ vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
+ vars["index"] = SimpleItoa(descriptor_->index());
+ vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
+ if (descriptor_->containing_type() != NULL) {
+ vars["parent"] = UniqueFileScopeIdentifier(
+ descriptor_->containing_type());
+ }
+ if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
+ // We can only make these package-private since the classes that use them
+ // are in separate files.
+ vars["private"] = "";
+ } else {
+ vars["private"] = "private ";
}
+ // 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"
+ " internal_$identifier$_descriptor;\n");
+
+ // And the FieldAccessorTable.
+ GenerateFieldAccessorTable(printer);
+
// Generate static members for all nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// TODO(kenton): Reuse MessageGenerator objects?
@@ -139,39 +144,42 @@ void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) {
}
}
-void ImmutableMessageGenerator::GenerateStaticVariableInitializers(
+int ImmutableMessageGenerator::GenerateStaticVariableInitializers(
io::Printer* printer) {
- if (HasDescriptorMethods(descriptor_)) {
- map<string, string> vars;
- vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
- vars["index"] = SimpleItoa(descriptor_->index());
- vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
- if (descriptor_->containing_type() != NULL) {
- vars["parent"] = UniqueFileScopeIdentifier(
- descriptor_->containing_type());
- }
-
- // The descriptor for this type.
- if (descriptor_->containing_type() == NULL) {
- printer->Print(vars,
- "internal_$identifier$_descriptor =\n"
- " getDescriptor().getMessageTypes().get($index$);\n");
- } else {
- printer->Print(vars,
- "internal_$identifier$_descriptor =\n"
- " internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
- }
+ int bytecode_estimate = 0;
+ map<string, string> vars;
+ vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
+ vars["index"] = SimpleItoa(descriptor_->index());
+ vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
+ if (descriptor_->containing_type() != NULL) {
+ vars["parent"] = UniqueFileScopeIdentifier(
+ descriptor_->containing_type());
+ }
- // And the FieldAccessorTable.
- GenerateFieldAccessorTableInitializer(printer);
+ // The descriptor for this type.
+ if (descriptor_->containing_type() == NULL) {
+ printer->Print(vars,
+ "internal_$identifier$_descriptor =\n"
+ " getDescriptor().getMessageTypes().get($index$);\n");
+ bytecode_estimate += 30;
+ } else {
+ printer->Print(vars,
+ "internal_$identifier$_descriptor =\n"
+ " internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
+ bytecode_estimate += 30;
}
+ // And the FieldAccessorTable.
+ bytecode_estimate += GenerateFieldAccessorTableInitializer(printer);
+
// Generate static member initializers for all nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// TODO(kenton): Reuse MessageGenerator objects?
- ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
- .GenerateStaticVariableInitializers(printer);
+ bytecode_estimate +=
+ ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
+ .GenerateStaticVariableInitializers(printer);
}
+ return bytecode_estimate;
}
void ImmutableMessageGenerator::
@@ -191,8 +199,9 @@ GenerateFieldAccessorTable(io::Printer* printer) {
" internal_$identifier$_fieldAccessorTable;\n");
}
-void ImmutableMessageGenerator::
+int ImmutableMessageGenerator::
GenerateFieldAccessorTableInitializer(io::Printer* printer) {
+ int bytecode_estimate = 10;
printer->Print(
"internal_$identifier$_fieldAccessorTable = new\n"
" com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n"
@@ -203,6 +212,7 @@ GenerateFieldAccessorTableInitializer(io::Printer* printer) {
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ bytecode_estimate += 6;
printer->Print(
"\"$field_name$\", ",
"field_name", info->capitalized_name);
@@ -210,50 +220,33 @@ GenerateFieldAccessorTableInitializer(io::Printer* printer) {
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
const OneofGeneratorInfo* info = context_->GetOneofGeneratorInfo(oneof);
+ bytecode_estimate += 6;
printer->Print(
"\"$oneof_name$\", ",
"oneof_name", info->capitalized_name);
}
printer->Print("});\n");
+ return bytecode_estimate;
}
// ===================================================================
void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public interface $classname$OrBuilder extends\n"
- " $extra_interfaces$\n"
- " com.google.protobuf.GeneratedMessage.\n"
- " ExtendableMessageOrBuilder<$classname$> {\n",
- "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
- "classname", descriptor_->name());
- } else {
- printer->Print(
- "public interface $classname$OrBuilder extends \n"
- " $extra_interfaces$\n"
- " com.google.protobuf.GeneratedMessageLite.\n"
- " ExtendableMessageOrBuilder<$classname$> {\n",
- "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
- "classname", descriptor_->name());
- }
+ printer->Print(
+ "public interface $classname$OrBuilder extends\n"
+ " $extra_interfaces$\n"
+ " com.google.protobuf.GeneratedMessage.\n"
+ " ExtendableMessageOrBuilder<$classname$> {\n",
+ "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+ "classname", descriptor_->name());
} else {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public interface $classname$OrBuilder extends\n"
- " $extra_interfaces$\n"
- " com.google.protobuf.MessageOrBuilder {\n",
- "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
- "classname", descriptor_->name());
- } else {
- printer->Print(
- "public interface $classname$OrBuilder extends\n"
- " $extra_interfaces$\n"
- " com.google.protobuf.MessageLiteOrBuilder {\n",
- "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
- "classname", descriptor_->name());
- }
+ printer->Print(
+ "public interface $classname$OrBuilder extends\n"
+ " $extra_interfaces$\n"
+ " com.google.protobuf.MessageOrBuilder {\n",
+ "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+ "classname", descriptor_->name());
}
printer->Indent();
@@ -278,7 +271,6 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
variables["static"] = is_own_file ? " " : " static ";
variables["classname"] = descriptor_->name();
variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
- variables["lite"] = HasDescriptorMethods(descriptor_) ? "" : "Lite";
WriteMessageDocComment(printer, descriptor_);
@@ -287,70 +279,63 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) {
printer->Print(variables,
"public $static$final class $classname$ extends\n"
- " com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage<\n"
+ " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
" $classname$> implements\n"
" $extra_interfaces$\n"
" $classname$OrBuilder {\n");
builder_type = strings::Substitute(
- "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
- name_resolver_->GetImmutableClassName(descriptor_),
- variables["lite"]);
+ "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>",
+ name_resolver_->GetImmutableClassName(descriptor_));
} else {
printer->Print(variables,
"public $static$final class $classname$ extends\n"
- " com.google.protobuf.GeneratedMessage$lite$ implements\n"
+ " com.google.protobuf.GeneratedMessage implements\n"
" $extra_interfaces$\n"
" $classname$OrBuilder {\n");
- builder_type = strings::Substitute(
- "com.google.protobuf.GeneratedMessage$0.Builder",
- variables["lite"]);
+
+ builder_type = "com.google.protobuf.GeneratedMessage.Builder";
}
printer->Indent();
- if (HasDescriptorMethods(descriptor_)) {
- // Using builder_type, instead of Builder, prevents the Builder class from
- // being loaded into PermGen space when the default instance is created.
- // This optimizes the PermGen space usage for clients that do not modify
- // messages.
- printer->Print(
- "// Use $classname$.newBuilder() to construct.\n"
- "private $classname$($buildertype$ builder) {\n"
- " super(builder);\n"
- "}\n",
- "classname", descriptor_->name(),
- "buildertype", builder_type);
- printer->Print(
- "private $classname$() {\n",
- "classname", descriptor_->name());
- printer->Indent();
- GenerateInitializers(printer);
- printer->Outdent();
- printer->Print(
- "}\n"
- "\n");
- }
+ // Using builder_type, instead of Builder, prevents the Builder class from
+ // being loaded into PermGen space when the default instance is created.
+ // This optimizes the PermGen space usage for clients that do not modify
+ // messages.
+ printer->Print(
+ "// Use $classname$.newBuilder() to construct.\n"
+ "private $classname$($buildertype$ builder) {\n"
+ " super(builder);\n"
+ "}\n",
+ "classname", descriptor_->name(),
+ "buildertype", builder_type);
+ printer->Print(
+ "private $classname$() {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+ GenerateInitializers(printer);
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
- if (HasDescriptorMethods(descriptor_)) {
+ printer->Print(
+ "@java.lang.Override\n"
+ "public final com.google.protobuf.UnknownFieldSet\n"
+ "getUnknownFields() {\n");
+ if (PreserveUnknownFields(descriptor_)) {
printer->Print(
- "@java.lang.Override\n"
- "public final com.google.protobuf.UnknownFieldSet\n"
- "getUnknownFields() {\n");
- if (PreserveUnknownFields(descriptor_)) {
- printer->Print(
- " return this.unknownFields;\n");
- } else {
- printer->Print(
- " return com.google.protobuf.UnknownFieldSet.getDefaultInstance();\n");
- }
+ " return this.unknownFields;\n");
+ } else {
printer->Print(
- "}\n");
+ " return com.google.protobuf.UnknownFieldSet.getDefaultInstance();\n");
}
+ printer->Print(
+ "}\n");
if (HasGeneratedMethods(descriptor_)) {
GenerateParsingConstructor(printer);
}
GenerateDescriptorMethods(printer);
- GenerateParser(printer);
// Nested types
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
@@ -460,7 +445,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
}
if (HasGeneratedMethods(descriptor_)) {
- GenerateIsInitialized(printer, MEMOIZE);
+ GenerateIsInitialized(printer);
GenerateMessageSerializationMethods(printer);
}
@@ -481,45 +466,33 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
// Carefully initialize the default instance in such a way that it doesn't
// conflict with other initialization.
printer->Print(
- "private static final $classname$ defaultInstance;",
+ "private static final $classname$ DEFAULT_INSTANCE;\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "static {\n"
- " defaultInstance = new $classname$();\n"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- } else {
- // LITE_RUNTIME only has one constructor.
- printer->Print(
- "static {\n"
- " try {\n"
- " defaultInstance = new $classname$(\n"
- " com.google.protobuf.Internal\n"
- " .EMPTY_CODED_INPUT_STREAM,\n"
- " com.google.protobuf.ExtensionRegistryLite\n"
- " .getEmptyRegistry());\n"
- " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
- " throw new ExceptionInInitializerError(e);\n"
- " }\n"
- "}\n"
- "\n",
- "classname", descriptor_->name());
- }
+ printer->Print(
+ "static {\n"
+ " DEFAULT_INSTANCE = new $classname$();\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
printer->Print(
"public static $classname$ getDefaultInstance() {\n"
- " return defaultInstance;\n"
- "}\n"
- "\n"
- "public $classname$ getDefaultInstanceForType() {\n"
- " return defaultInstance;\n"
+ " return DEFAULT_INSTANCE;\n"
"}\n"
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
- // Extensions must be declared after the defaultInstance is initialized
- // because the defaultInstance is used by the extension to lazily retrieve
+ GenerateParser(printer);
+
+ printer->Print(
+ "public $classname$ getDefaultInstanceForType() {\n"
+ " return DEFAULT_INSTANCE;\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ // Extensions must be declared after the DEFAULT_INSTANCE is initialized
+ // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
// the outer class's FileDescriptor.
for (int i = 0; i < descriptor_->extension_count(); i++) {
ImmutableExtensionGenerator(descriptor_->extension(i), context_)
@@ -542,36 +515,36 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
sorted_extensions.push_back(descriptor_->extension_range(i));
}
- sort(sorted_extensions.begin(), sorted_extensions.end(),
- ExtensionRangeOrdering());
+ std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+ ExtensionRangeOrdering());
printer->Print(
"public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
" throws java.io.IOException {\n");
printer->Indent();
- // writeTo(CodedOutputStream output) might be invoked without
- // getSerializedSize() ever being called, but we need the memoized
- // sizes in case this message has packed fields. Rather than emit checks for
- // each packed field, just call getSerializedSize() up front for all messages.
- // In most cases, getSerializedSize() will have already been called anyway by
- // one of the wrapper writeTo() methods, making this call cheap.
- printer->Print(
- "getSerializedSize();\n");
+ if (HasPackedFields(descriptor_)) {
+ // writeTo(CodedOutputStream output) might be invoked without
+ // getSerializedSize() ever being called, but we need the memoized
+ // sizes in case this message has packed fields. Rather than emit checks for
+ // each packed field, just call getSerializedSize() up front.
+ // In most cases, getSerializedSize() will have already been called anyway
+ // by one of the wrapper writeTo() methods, making this call cheap.
+ printer->Print(
+ "getSerializedSize();\n");
+ }
if (descriptor_->extension_range_count() > 0) {
if (descriptor_->options().message_set_wire_format()) {
printer->Print(
- "com.google.protobuf.GeneratedMessage$lite$\n"
- " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n"
- " newMessageSetExtensionWriter();\n",
- "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite",
+ "com.google.protobuf.GeneratedMessage\n"
+ " .ExtendableMessage<$classname$>.ExtensionWriter\n"
+ " extensionWriter = newMessageSetExtensionWriter();\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
} else {
printer->Print(
- "com.google.protobuf.GeneratedMessage$lite$\n"
- " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n"
- " newExtensionWriter();\n",
- "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite",
+ "com.google.protobuf.GeneratedMessage\n"
+ " .ExtendableMessage<$classname$>.ExtensionWriter\n"
+ " extensionWriter = newExtensionWriter();\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
}
}
@@ -592,8 +565,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
}
if (PreserveUnknownFields(descriptor_)) {
- if (descriptor_->options().message_set_wire_format()
- && HasDescriptorMethods(descriptor_)) {
+ if (descriptor_->options().message_set_wire_format()) {
printer->Print(
"unknownFields.writeAsMessageSetTo(output);\n");
} else {
@@ -629,8 +601,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
}
if (PreserveUnknownFields(descriptor_)) {
- if (descriptor_->options().message_set_wire_format()
- && HasDescriptorMethods(descriptor_)) {
+ if (descriptor_->options().message_set_wire_format()) {
printer->Print(
"size += unknownFields.getSerializedSizeAsMessageSet();\n");
} else {
@@ -727,570 +698,115 @@ void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange(
// ===================================================================
void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
+ // LITE_RUNTIME implements this at the GeneratedMessageLite level.
+ printer->Print(
+ "public Builder newBuilderForType() { return newBuilder(); }\n");
+
printer->Print(
- "public static Builder newBuilder() { return new Builder(); }\n"
- "public Builder newBuilderForType() { return newBuilder(); }\n"
+ "public static Builder newBuilder() {\n"
+ " return DEFAULT_INSTANCE.toBuilder();\n"
+ "}\n"
"public static Builder newBuilder($classname$ prototype) {\n"
- " return newBuilder().mergeFrom(prototype);\n"
+ " return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n"
+ "}\n"
+ "public Builder toBuilder() {\n"
+ " return this == DEFAULT_INSTANCE\n"
+ " ? new Builder() : new Builder().mergeFrom(this);\n"
"}\n"
- "public Builder toBuilder() { return newBuilder(this); }\n"
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
- if (HasNestedBuilders(descriptor_)) {
- printer->Print(
- "@java.lang.Override\n"
- "protected Builder newBuilderForType(\n"
- " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
- " Builder builder = new Builder(parent);\n"
- " return builder;\n"
- "}\n");
- }
-
- WriteMessageDocComment(printer, descriptor_);
-
- if (descriptor_->extension_range_count() > 0) {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public static final class Builder extends\n"
- " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
- " $classname$, Builder> implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_),
- "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
- } else {
- printer->Print(
- "public static final class Builder extends\n"
- " com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n"
- " $classname$, Builder> implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_),
- "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
- }
- } else {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public static final class Builder extends\n"
- " com.google.protobuf.GeneratedMessage.Builder<Builder> implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_),
- "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
- } else {
- printer->Print(
- "public static final class Builder extends\n"
- " com.google.protobuf.GeneratedMessageLite.Builder<\n"
- " $classname$, Builder>\n"
- " implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_),
- "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
- }
- }
- printer->Indent();
-
- GenerateDescriptorMethods(printer);
- GenerateCommonBuilderMethods(printer);
-
- if (HasGeneratedMethods(descriptor_)) {
- GenerateIsInitialized(printer, DONT_MEMOIZE);
- GenerateBuilderParsingMethods(printer);
- }
-
- // oneof
- map<string, string> vars;
- for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- vars["oneof_name"] = context_->GetOneofGeneratorInfo(
- descriptor_->oneof_decl(i))->name;
- vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(
- descriptor_->oneof_decl(i))->capitalized_name;
- vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
- // oneofCase_ and oneof_
- printer->Print(vars,
- "private int $oneof_name$Case_ = 0;\n"
- "private java.lang.Object $oneof_name$_;\n");
- // oneofCase() and clearOneof()
- printer->Print(vars,
- "public $oneof_capitalized_name$Case\n"
- " get$oneof_capitalized_name$Case() {\n"
- " return $oneof_capitalized_name$Case.valueOf(\n"
- " $oneof_name$Case_);\n"
- "}\n"
- "\n"
- "public Builder clear$oneof_capitalized_name$() {\n"
- " $oneof_name$Case_ = 0;\n"
- " $oneof_name$_ = null;\n");
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(" onChanged();\n");
- }
- printer->Print(
- " return this;\n"
- "}\n"
- "\n");
- }
-
- 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))
- .GetNumBitsForBuilder();
- }
- int totalInts = (totalBits + 31) / 32;
- for (int i = 0; i < totalInts; i++) {
- printer->Print("private int $bit_field_name$;\n",
- "bit_field_name", GetBitFieldName(i));
- }
- }
-
- for (int i = 0; i < descriptor_->field_count(); i++) {
- printer->Print("\n");
- field_generators_.get(descriptor_->field(i))
- .GenerateBuilderMembers(printer);
- }
-
- 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",
- "full_name", descriptor_->full_name());
-
- printer->Outdent();
- printer->Print("}\n");
+ "@java.lang.Override\n"
+ "protected Builder newBuilderForType(\n"
+ " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
+ " Builder builder = new Builder(parent);\n"
+ " return builder;\n"
+ "}\n");
+
+ MessageBuilderGenerator builderGenerator(descriptor_, context_);
+ builderGenerator.Generate(printer);
}
void ImmutableMessageGenerator::
GenerateDescriptorMethods(io::Printer* printer) {
- if (HasDescriptorMethods(descriptor_)) {
- if (!descriptor_->options().no_standard_descriptor_accessor()) {
- printer->Print(
- "public static final com.google.protobuf.Descriptors.Descriptor\n"
- " getDescriptor() {\n"
- " return $fileclass$.internal_$identifier$_descriptor;\n"
- "}\n"
- "\n",
- "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
- "identifier", UniqueFileScopeIdentifier(descriptor_));
- }
- vector<const FieldDescriptor*> map_fields;
- for (int i = 0; i < descriptor_->field_count(); i++) {
- const FieldDescriptor* field = descriptor_->field(i);
- if (GetJavaType(field) == JAVATYPE_MESSAGE &&
- IsMapEntry(field->message_type())) {
- map_fields.push_back(field);
- }
- }
- if (!map_fields.empty()) {
- printer->Print(
- "@SuppressWarnings({\"rawtypes\"})\n"
- "protected com.google.protobuf.MapField internalGetMapField(\n"
- " int number) {\n"
- " switch (number) {\n");
- printer->Indent();
- printer->Indent();
- for (int i = 0; i < map_fields.size(); ++i) {
- const FieldDescriptor* field = map_fields[i];
- const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
- printer->Print(
- "case $number$:\n"
- " return $name$_;\n",
- "number", SimpleItoa(field->number()),
- "name", info->name);
- }
- printer->Print(
- "default:\n"
- " throw new RuntimeException(\n"
- " \"Invalid map field number: \" + number);\n");
- printer->Outdent();
- printer->Outdent();
- printer->Print(
- " }\n"
- "}\n");
- }
+ if (!descriptor_->options().no_standard_descriptor_accessor()) {
printer->Print(
- "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
- " internalGetFieldAccessorTable() {\n"
- " return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
- " .ensureFieldAccessorsInitialized(\n"
- " $classname$.class, $classname$.Builder.class);\n"
+ "public static final com.google.protobuf.Descriptors.Descriptor\n"
+ " getDescriptor() {\n"
+ " return $fileclass$.internal_$identifier$_descriptor;\n"
"}\n"
"\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_),
"fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
"identifier", UniqueFileScopeIdentifier(descriptor_));
}
-}
-
-// ===================================================================
-
-void ImmutableMessageGenerator::
-GenerateCommonBuilderMethods(io::Printer* printer) {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "// Construct using $classname$.newBuilder()\n"
- "private Builder() {\n"
- " maybeForceBuilderInitialization();\n"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
-
- printer->Print(
- "private Builder(\n"
- " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
- " super(parent);\n"
- " maybeForceBuilderInitialization();\n"
- "}\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- } else {
- // LITE runtime passes along the default instance to implement
- // getDefaultInstanceForType() at the GneratedMessageLite level.
- printer->Print(
- "// Construct using $classname$.newBuilder()\n"
- "private Builder() {\n"
- " super(defaultInstance);\n"
- " maybeForceBuilderInitialization();\n"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ vector<const FieldDescriptor*> map_fields;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+ IsMapEntry(field->message_type())) {
+ map_fields.push_back(field);
+ }
}
-
-
- if (HasNestedBuilders(descriptor_)) {
+ if (!map_fields.empty()) {
printer->Print(
- "private void maybeForceBuilderInitialization() {\n"
- " if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n");
-
+ "@SuppressWarnings({\"rawtypes\"})\n"
+ "protected com.google.protobuf.MapField internalGetMapField(\n"
+ " int number) {\n"
+ " switch (number) {\n");
printer->Indent();
printer->Indent();
- for (int i = 0; i < descriptor_->field_count(); i++) {
- if (!descriptor_->field(i)->containing_oneof()) {
- field_generators_.get(descriptor_->field(i))
- .GenerateFieldBuilderInitializationCode(printer);
- }
+ for (int i = 0; i < map_fields.size(); ++i) {
+ const FieldDescriptor* field = map_fields[i];
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ printer->Print(
+ "case $number$:\n"
+ " return internalGet$capitalized_name$();\n",
+ "number", SimpleItoa(field->number()),
+ "capitalized_name", info->capitalized_name);
}
+ printer->Print(
+ "default:\n"
+ " throw new RuntimeException(\n"
+ " \"Invalid map field number: \" + number);\n");
printer->Outdent();
printer->Outdent();
-
- printer->Print(
- " }\n"
- "}\n");
- } else {
- printer->Print(
- "private void maybeForceBuilderInitialization() {\n"
- "}\n");
- }
-
- printer->Print(
- "public Builder clear() {\n"
- " super.clear();\n");
-
- printer->Indent();
-
- for (int i = 0; i < descriptor_->field_count(); i++) {
- if (!descriptor_->field(i)->containing_oneof()) {
- field_generators_.get(descriptor_->field(i))
- .GenerateBuilderClearCode(printer);
- }
- }
-
- for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- printer->Print(
- "$oneof_name$Case_ = 0;\n"
- "$oneof_name$_ = null;\n",
- "oneof_name", context_->GetOneofGeneratorInfo(
- descriptor_->oneof_decl(i))->name);
- }
-
- printer->Outdent();
-
- printer->Print(
- " return this;\n"
- "}\n"
- "\n");
-
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public com.google.protobuf.Descriptors.Descriptor\n"
- " getDescriptorForType() {\n"
- " return $fileclass$.internal_$identifier$_descriptor;\n"
- "}\n"
- "\n",
- "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
- "identifier", UniqueFileScopeIdentifier(descriptor_));
-
- // LITE runtime implements this in GeneratedMessageLite.
- printer->Print(
- "public $classname$ getDefaultInstanceForType() {\n"
- " return $classname$.getDefaultInstance();\n"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- }
-
- // -----------------------------------------------------------------
-
- if (HasDescriptorMethods(descriptor_)) {
- // LITE implements build in GeneratedMessageLite to save methods.
- printer->Print(
- "public $classname$ build() {\n"
- " $classname$ result = buildPartial();\n"
- " if (!result.isInitialized()) {\n"
- " throw newUninitializedMessageException(result);\n"
- " }\n"
- " return result;\n"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- }
-
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public $classname$ buildPartial() {\n"
- " $classname$ result = new $classname$(this);\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- } else {
- // LITE_RUNTIME only provides a single message constructor.
printer->Print(
- "public $classname$ buildPartial() {\n"
- " $classname$ result = null;\n"
- " try {\n"
- " result = new $classname$(\n"
- " com.google.protobuf.Internal\n"
- " .EMPTY_CODED_INPUT_STREAM,\n"
- " com.google.protobuf.ExtensionRegistryLite\n"
- " .getEmptyRegistry());\n"
- " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
- " throw new RuntimeException(e);\n"
" }\n"
- " result.unknownFields = this.unknownFields;\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
-
- if (descriptor_->extension_range_count() > 0) {
- printer->Print(
- " result.extensions = this.buildExtensions();\n");
- }
- }
-
- printer->Indent();
-
- int totalBuilderBits = 0;
- int totalMessageBits = 0;
- for (int i = 0; i < descriptor_->field_count(); i++) {
- const ImmutableFieldGenerator& field =
- field_generators_.get(descriptor_->field(i));
- totalBuilderBits += field.GetNumBitsForBuilder();
- totalMessageBits += field.GetNumBitsForMessage();
- }
- int totalBuilderInts = (totalBuilderBits + 31) / 32;
- int totalMessageInts = (totalMessageBits + 31) / 32;
-
- if (GenerateHasBits(descriptor_)) {
- // Local vars for from and to bit fields to avoid accessing the builder and
- // message over and over for these fields. Seems to provide a slight
- // perforamance improvement in micro benchmark and this is also what proto1
- // code does.
- for (int i = 0; i < totalBuilderInts; i++) {
- printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n",
- "bit_field_name", GetBitFieldName(i));
- }
- for (int i = 0; i < totalMessageInts; i++) {
- printer->Print("int to_$bit_field_name$ = 0;\n",
- "bit_field_name", GetBitFieldName(i));
- }
- }
-
- // Output generation code for each field.
- for (int i = 0; i < descriptor_->field_count(); i++) {
- field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer);
- }
-
- if (GenerateHasBits(descriptor_)) {
- // Copy the bit field results to the generated message
- for (int i = 0; i < totalMessageInts; i++) {
- printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n",
- "bit_field_name", GetBitFieldName(i));
- }
- }
-
- for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n",
- "oneof_name", context_->GetOneofGeneratorInfo(
- descriptor_->oneof_decl(i))->name);
- }
-
- printer->Outdent();
-
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- " onBuilt();\n");
+ "}\n");
}
-
printer->Print(
- " return result;\n"
+ "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+ " internalGetFieldAccessorTable() {\n"
+ " return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
+ " .ensureFieldAccessorsInitialized(\n"
+ " $classname$.class, $classname$.Builder.class);\n"
"}\n"
"\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
-
- // -----------------------------------------------------------------
-
- if (HasGeneratedMethods(descriptor_)) {
- // MergeFrom(Message other) requires the ability to distinguish the other
- // messages type by its descriptor.
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public Builder mergeFrom(com.google.protobuf.Message other) {\n"
- " if (other instanceof $classname$) {\n"
- " return mergeFrom(($classname$)other);\n"
- " } else {\n"
- " super.mergeFrom(other);\n"
- " return this;\n"
- " }\n"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- }
-
- printer->Print(
- "public Builder mergeFrom($classname$ other) {\n"
- // Optimization: If other is the default instance, we know none of its
- // fields are set so we can skip the merge.
- " if (other == $classname$.getDefaultInstance()) return this;\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- printer->Indent();
-
- for (int i = 0; i < descriptor_->field_count(); i++) {
- if (!descriptor_->field(i)->containing_oneof()) {
- field_generators_.get(
- descriptor_->field(i)).GenerateMergingCode(printer);
- }
- }
-
- // Merge oneof fields.
- for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
- printer->Print(
- "switch (other.get$oneof_capitalized_name$Case()) {\n",
- "oneof_capitalized_name",
- context_->GetOneofGeneratorInfo(
- descriptor_->oneof_decl(i))->capitalized_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(
- "case $field_name$: {\n",
- "field_name",
- ToUpper(field->name()));
- printer->Indent();
- field_generators_.get(field).GenerateMergingCode(printer);
- printer->Print(
- "break;\n");
- printer->Outdent();
- printer->Print(
- "}\n");
- }
- printer->Print(
- "case $cap_oneof_name$_NOT_SET: {\n"
- " break;\n"
- "}\n",
- "cap_oneof_name",
- ToUpper(context_->GetOneofGeneratorInfo(
- descriptor_->oneof_decl(i))->name));
- printer->Outdent();
- printer->Print(
- "}\n");
- }
-
- printer->Outdent();
-
- // if message type has extensions
- if (descriptor_->extension_range_count() > 0) {
- printer->Print(
- " this.mergeExtensionFields(other);\n");
- }
-
- if (PreserveUnknownFields(descriptor_)) {
- printer->Print(
- " this.mergeUnknownFields(other.unknownFields);\n");
- }
-
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(" onChanged();\n");
- }
-
- printer->Print(
- " return this;\n"
- "}\n"
- "\n");
- }
-}
-
-// ===================================================================
-
-void ImmutableMessageGenerator::
-GenerateBuilderParsingMethods(io::Printer* printer) {
- if (HasDescriptorMethods(descriptor_)) {
- // LITE_RUNTIME implements this at the GeneratedMessageLite level.
- printer->Print(
- "public Builder mergeFrom(\n"
- " com.google.protobuf.CodedInputStream input,\n"
- " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
- " throws java.io.IOException {\n"
- " $classname$ parsedMessage = null;\n"
- " try {\n"
- " parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n"
- " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
- " parsedMessage = ($classname$) e.getUnfinishedMessage();\n"
- " throw e;\n"
- " } finally {\n"
- " if (parsedMessage != null) {\n"
- " mergeFrom(parsedMessage);\n"
- " }\n"
- " }\n"
- " return this;\n"
- "}\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- }
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+ "identifier", UniqueFileScopeIdentifier(descriptor_));
}
// ===================================================================
void ImmutableMessageGenerator::GenerateIsInitialized(
- io::Printer* printer, UseMemoization useMemoization) {
- bool memoization = useMemoization == MEMOIZE;
- if (memoization) {
- // Memoizes whether the protocol buffer is fully initialized (has all
- // required fields). -1 means not yet computed. 0 means false and 1 means
- // true.
- printer->Print(
- "private byte memoizedIsInitialized = -1;\n");
- }
+ io::Printer* printer) {
+ // Memoizes whether the protocol buffer is fully initialized (has all
+ // required fields). -1 means not yet computed. 0 means false and 1 means
+ // true.
+ printer->Print(
+ "private byte memoizedIsInitialized = -1;\n");
printer->Print(
"public final boolean isInitialized() {\n");
printer->Indent();
- if (memoization) {
- // Don't directly compare to -1 to avoid an Android x86 JIT bug.
- printer->Print(
- "byte isInitialized = memoizedIsInitialized;\n"
- "if (isInitialized == 1) return true;\n"
- "if (isInitialized == 0) return false;\n"
- "\n");
- }
+ // Don't directly compare to -1 to avoid an Android x86 JIT bug.
+ printer->Print(
+ "byte isInitialized = memoizedIsInitialized;\n"
+ "if (isInitialized == 1) return true;\n"
+ "if (isInitialized == 0) return false;\n"
+ "\n");
// Check that all required fields in this message are set.
// TODO(kenton): We can optimize this when we switch to putting all the
@@ -1302,11 +818,10 @@ void ImmutableMessageGenerator::GenerateIsInitialized(
if (field->is_required()) {
printer->Print(
"if (!has$name$()) {\n"
- " $memoize$\n"
+ " memoizedIsInitialized = 0;\n"
" return false;\n"
"}\n",
- "name", info->capitalized_name,
- "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
+ "name", info->capitalized_name);
}
}
@@ -1320,13 +835,12 @@ void ImmutableMessageGenerator::GenerateIsInitialized(
case FieldDescriptor::LABEL_REQUIRED:
printer->Print(
"if (!get$name$().isInitialized()) {\n"
- " $memoize$\n"
+ " memoizedIsInitialized = 0;\n"
" return false;\n"
"}\n",
"type", name_resolver_->GetImmutableClassName(
field->message_type()),
- "name", info->capitalized_name,
- "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
+ "name", info->capitalized_name);
break;
case FieldDescriptor::LABEL_OPTIONAL:
if (!SupportFieldPresence(descriptor_->file()) &&
@@ -1345,38 +859,35 @@ void ImmutableMessageGenerator::GenerateIsInitialized(
}
printer->Print(
" if (!get$name$().isInitialized()) {\n"
- " $memoize$\n"
+ " memoizedIsInitialized = 0;\n"
" return false;\n"
" }\n"
"}\n",
- "name", info->capitalized_name,
- "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
+ "name", info->capitalized_name);
break;
case FieldDescriptor::LABEL_REPEATED:
if (IsMapEntry(field->message_type())) {
printer->Print(
"for ($type$ item : get$name$().values()) {\n"
" if (!item.isInitialized()) {\n"
- " $memoize$\n"
+ " memoizedIsInitialized = 0;\n"
" return false;\n"
" }\n"
"}\n",
"type", MapValueImmutableClassdName(field->message_type(),
name_resolver_),
- "name", info->capitalized_name,
- "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
+ "name", info->capitalized_name);
} else {
printer->Print(
"for (int i = 0; i < get$name$Count(); i++) {\n"
" if (!get$name$(i).isInitialized()) {\n"
- " $memoize$\n"
+ " memoizedIsInitialized = 0;\n"
" return false;\n"
" }\n"
"}\n",
"type", name_resolver_->GetImmutableClassName(
field->message_type()),
- "name", info->capitalized_name,
- "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
+ "name", info->capitalized_name);
}
break;
}
@@ -1386,18 +897,15 @@ void ImmutableMessageGenerator::GenerateIsInitialized(
if (descriptor_->extension_range_count() > 0) {
printer->Print(
"if (!extensionsAreInitialized()) {\n"
- " $memoize$\n"
+ " memoizedIsInitialized = 0;\n"
" return false;\n"
- "}\n",
- "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
+ "}\n");
}
printer->Outdent();
- if (memoization) {
- printer->Print(
- " memoizedIsInitialized = 1;\n");
- }
+ printer->Print(
+ " memoizedIsInitialized = 1;\n");
printer->Print(
" return true;\n"
@@ -1463,12 +971,10 @@ GenerateEqualsAndHashCode(io::Printer* printer) {
printer->Print(
"result = result && unknownFields.equals(other.unknownFields);\n");
}
- if (HasDescriptorMethods(descriptor_)) {
- if (descriptor_->extension_range_count() > 0) {
- printer->Print(
- "result = result &&\n"
- " getExtensionFields().equals(other.getExtensionFields());\n");
- }
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "result = result &&\n"
+ " getExtensionFields().equals(other.getExtensionFields());\n");
}
printer->Print(
"return result;\n");
@@ -1491,14 +997,7 @@ GenerateEqualsAndHashCode(io::Printer* printer) {
"}\n"
"int hash = 41;\n");
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n");
- } else {
- // 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_));
- }
+ printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n");
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
@@ -1516,11 +1015,9 @@ GenerateEqualsAndHashCode(io::Printer* printer) {
printer->Print("}\n");
}
}
- if (HasDescriptorMethods(descriptor_)) {
- if (descriptor_->extension_range_count() > 0) {
- printer->Print(
- "hash = hashFields(hash, getExtensionFields());\n");
- }
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "hash = hashFields(hash, getExtensionFields());\n");
}
printer->Print(
@@ -1558,19 +1055,13 @@ GenerateParsingConstructor(io::Printer* printer) {
printer->Print(
"private $classname$(\n"
" com.google.protobuf.CodedInputStream input,\n"
- " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
- " throws com.google.protobuf.InvalidProtocolBufferException {\n",
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n",
"classname", descriptor_->name());
printer->Indent();
// Initialize all fields to default.
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "this();\n");
- } else {
- // LITE_RUNTIME only has one constructor.
- GenerateInitializers(printer);
- }
+ printer->Print(
+ "this();\n");
// Use builder bits to track mutable repeated fields.
int totalBuilderBits = 0;
@@ -1586,15 +1077,9 @@ GenerateParsingConstructor(io::Printer* printer) {
}
if (PreserveUnknownFields(descriptor_)) {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
- " com.google.protobuf.UnknownFieldSet.newBuilder();\n");
- } else {
- printer->Print(
- "com.google.protobuf.UnknownFieldSetLite.Builder unknownFields =\n"
- " com.google.protobuf.UnknownFieldSetLite.newBuilder();\n");
- }
+ printer->Print(
+ "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
+ " com.google.protobuf.UnknownFieldSet.newBuilder();\n");
}
printer->Print(
@@ -1617,29 +1102,14 @@ GenerateParsingConstructor(io::Printer* printer) {
" break;\n");
if (PreserveUnknownFields(descriptor_)) {
- if (!HasDescriptorMethods(descriptor_)
- && descriptor_->extension_range_count() > 0) {
- // Lite runtime directly invokes parseUnknownField to reduce method
- // counts.
- printer->Print(
- "default: {\n"
- " if (!parseUnknownField(extensions, getDefaultInstanceForType(),\n"
- " input, unknownFields,\n"
- " extensionRegistry, tag)) {\n"
- " done = true;\n" // it's an endgroup tag
- " }\n"
- " break;\n"
- "}\n");
- } else {
- printer->Print(
- "default: {\n"
- " if (!parseUnknownField(input, unknownFields,\n"
- " extensionRegistry, tag)) {\n"
- " done = true;\n" // it's an endgroup tag
- " }\n"
- " break;\n"
- "}\n");
- }
+ printer->Print(
+ "default: {\n"
+ " if (!parseUnknownField(input, unknownFields,\n"
+ " extensionRegistry, tag)) {\n"
+ " done = true;\n" // it's an endgroup tag
+ " }\n"
+ " break;\n"
+ "}\n");
} else {
printer->Print(
"default: {\n"
@@ -1695,10 +1165,11 @@ GenerateParsingConstructor(io::Printer* printer) {
printer->Outdent();
printer->Print(
"} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
- " throw e.setUnfinishedMessage(this);\n"
+ " throw new RuntimeException(e.setUnfinishedMessage(this));\n"
"} catch (java.io.IOException e) {\n"
- " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
- " e.getMessage()).setUnfinishedMessage(this);\n"
+ " throw new RuntimeException(\n"
+ " new com.google.protobuf.InvalidProtocolBufferException(\n"
+ " e.getMessage()).setUnfinishedMessage(this));\n"
"} finally {\n");
printer->Indent();
@@ -1713,18 +1184,9 @@ GenerateParsingConstructor(io::Printer* printer) {
printer->Print("this.unknownFields = unknownFields.build();\n");
}
- if (!HasDescriptorMethods(descriptor_)) {
- // LITE runtime uses a static method to reduce method count.
- if (descriptor_->extension_range_count() > 0) {
- // Make extensions immutable.
- printer->Print(
- "makeExtensionsImmutable(extensions);\n");
- }
- } else {
- // Make extensions immutable.
- printer->Print(
- "makeExtensionsImmutable();\n");
- }
+ // Make extensions immutable.
+ printer->Print(
+ "makeExtensionsImmutable();\n");
printer->Outdent();
printer->Outdent();
@@ -1747,13 +1209,24 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
" throws com.google.protobuf.InvalidProtocolBufferException {\n",
"classname", descriptor_->name());
if (HasGeneratedMethods(descriptor_)) {
+ // The parsing constructor throws an InvalidProtocolBufferException via a
+ // RuntimeException to aid in method pruning. We unwrap it here.
printer->Print(
- " return new $classname$(input, extensionRegistry);\n",
+ " try {\n"
+ " return new $classname$(input, extensionRegistry);\n"
+ " } catch (RuntimeException e) {\n"
+ " if (e.getCause() instanceof\n"
+ " com.google.protobuf.InvalidProtocolBufferException) {\n"
+ " throw (com.google.protobuf.InvalidProtocolBufferException)\n"
+ " e.getCause();\n"
+ " }\n"
+ " throw e;\n"
+ " }\n",
"classname", descriptor_->name());
} else {
- // When parsing constructor isn't generated, use builder to parse messages.
- // Note, will fallback to use reflection based mergeFieldFrom() in
- // AbstractMessage.Builder.
+ // When parsing constructor isn't generated, use builder to parse
+ // messages. Note, will fallback to use reflection based mergeFieldFrom()
+ // in AbstractMessage.Builder.
printer->Indent();
printer->Print(
"Builder builder = newBuilder();\n"
@@ -1763,7 +1236,8 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
" throw e.setUnfinishedMessage(builder.buildPartial());\n"
"} catch (java.io.IOException e) {\n"
" throw new com.google.protobuf.InvalidProtocolBufferException(\n"
- " e.getMessage()).setUnfinishedMessage(builder.buildPartial());\n"
+ " e.getMessage()).setUnfinishedMessage(\n"
+ " builder.buildPartial());\n"
"}\n"
"return builder.buildPartial();\n");
printer->Outdent();
diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h
index 91eb2876..c3c37765 100644
--- a/src/google/protobuf/compiler/java/java_message.h
+++ b/src/google/protobuf/compiler/java/java_message.h
@@ -67,8 +67,8 @@ class MessageGenerator {
virtual void GenerateStaticVariables(io::Printer* printer) = 0;
// Output code which initializes the static variables generated by
- // GenerateStaticVariables().
- virtual void GenerateStaticVariableInitializers(io::Printer* printer) = 0;
+ // GenerateStaticVariables(). Returns an estimate of bytecode size.
+ virtual int GenerateStaticVariableInitializers(io::Printer* printer) = 0;
// Generate the class itself.
virtual void Generate(io::Printer* printer) = 0;
@@ -97,16 +97,16 @@ class ImmutableMessageGenerator : public MessageGenerator {
virtual void GenerateInterface(io::Printer* printer);
virtual void GenerateExtensionRegistrationCode(io::Printer* printer);
virtual void GenerateStaticVariables(io::Printer* printer);
- virtual void GenerateStaticVariableInitializers(io::Printer* printer);
+
+ // Returns an estimate of the number of bytes the printed code will compile to
+ virtual int GenerateStaticVariableInitializers(io::Printer* printer);
private:
- enum UseMemoization {
- MEMOIZE,
- DONT_MEMOIZE
- };
void GenerateFieldAccessorTable(io::Printer* printer);
- void GenerateFieldAccessorTableInitializer(io::Printer* printer);
+
+ // Returns an estimate of the number of bytes the printed code will compile to
+ int GenerateFieldAccessorTableInitializer(io::Printer* printer);
void GenerateMessageSerializationMethods(io::Printer* printer);
void GenerateParseFromMethods(io::Printer* printer);
@@ -116,11 +116,8 @@ class ImmutableMessageGenerator : public MessageGenerator {
io::Printer* printer, const Descriptor::ExtensionRange* range);
void GenerateBuilder(io::Printer* printer);
- void GenerateCommonBuilderMethods(io::Printer* printer);
+ void GenerateIsInitialized(io::Printer* printer);
void GenerateDescriptorMethods(io::Printer* printer);
- void GenerateBuilderParsingMethods(io::Printer* printer);
- void GenerateIsInitialized(io::Printer* printer,
- UseMemoization useMemoization);
void GenerateInitializers(io::Printer* printer);
void GenerateEqualsAndHashCode(io::Printer* printer);
void GenerateParser(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
new file mode 100644
index 00000000..72694119
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_builder.cc
@@ -0,0 +1,661 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_message_builder.h>
+
+#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 <vector>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum.h>
+#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_generator_factory.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+bool GenerateHasBits(const Descriptor* descriptor) {
+ return SupportFieldPresence(descriptor->file()) ||
+ HasRepeatedFields(descriptor);
+}
+
+string MapValueImmutableClassdName(const Descriptor* descriptor,
+ ClassNameResolver* name_resolver) {
+ const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
+ return name_resolver->GetImmutableClassName(value_field->message_type());
+}
+} // namespace
+
+MessageBuilderGenerator::MessageBuilderGenerator(
+ const Descriptor* descriptor, Context* context)
+ : descriptor_(descriptor), context_(context),
+ name_resolver_(context->GetNameResolver()),
+ field_generators_(descriptor, context_) {
+ GOOGLE_CHECK_NE(
+ FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+}
+
+MessageBuilderGenerator::~MessageBuilderGenerator() {}
+
+void MessageBuilderGenerator::
+Generate(io::Printer* printer) {
+ WriteMessageDocComment(printer, descriptor_);
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "public static final class Builder extends\n"
+ " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
+ " $classname$, Builder> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
+ } else {
+ printer->Print(
+ "public static final class Builder extends\n"
+ " com.google.protobuf.GeneratedMessage.Builder<Builder> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
+ }
+ printer->Indent();
+
+ GenerateDescriptorMethods(printer);
+ GenerateCommonBuilderMethods(printer);
+
+ if (HasGeneratedMethods(descriptor_)) {
+ GenerateIsInitialized(printer);
+ GenerateBuilderParsingMethods(printer);
+ }
+
+ // oneof
+ map<string, string> vars;
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ vars["oneof_name"] = context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->name;
+ vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->capitalized_name;
+ vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+ // oneofCase_ and oneof_
+ printer->Print(vars,
+ "private int $oneof_name$Case_ = 0;\n"
+ "private java.lang.Object $oneof_name$_;\n");
+ // oneofCase() and clearOneof()
+ printer->Print(vars,
+ "public $oneof_capitalized_name$Case\n"
+ " get$oneof_capitalized_name$Case() {\n"
+ " return $oneof_capitalized_name$Case.valueOf(\n"
+ " $oneof_name$Case_);\n"
+ "}\n"
+ "\n"
+ "public Builder clear$oneof_capitalized_name$() {\n"
+ " $oneof_name$Case_ = 0;\n"
+ " $oneof_name$_ = null;\n");
+ printer->Print(" onChanged();\n");
+ printer->Print(
+ " return this;\n"
+ "}\n"
+ "\n");
+ }
+
+ 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))
+ .GetNumBitsForBuilder();
+ }
+ int totalInts = (totalBits + 31) / 32;
+ for (int i = 0; i < totalInts; i++) {
+ printer->Print("private int $bit_field_name$;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+ }
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("\n");
+ field_generators_.get(descriptor_->field(i))
+ .GenerateBuilderMembers(printer);
+ }
+
+ 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",
+ "full_name", descriptor_->full_name());
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+// ===================================================================
+
+void MessageBuilderGenerator::
+GenerateDescriptorMethods(io::Printer* printer) {
+ if (!descriptor_->options().no_standard_descriptor_accessor()) {
+ printer->Print(
+ "public static final com.google.protobuf.Descriptors.Descriptor\n"
+ " getDescriptor() {\n"
+ " return $fileclass$.internal_$identifier$_descriptor;\n"
+ "}\n"
+ "\n",
+ "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+ "identifier", UniqueFileScopeIdentifier(descriptor_));
+ }
+ vector<const FieldDescriptor*> map_fields;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+ IsMapEntry(field->message_type())) {
+ map_fields.push_back(field);
+ }
+ }
+ if (!map_fields.empty()) {
+ printer->Print(
+ "@SuppressWarnings({\"rawtypes\"})\n"
+ "protected com.google.protobuf.MapField internalGetMapField(\n"
+ " int number) {\n"
+ " switch (number) {\n");
+ printer->Indent();
+ printer->Indent();
+ for (int i = 0; i < map_fields.size(); ++i) {
+ const FieldDescriptor* field = map_fields[i];
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ printer->Print(
+ "case $number$:\n"
+ " return internalGet$capitalized_name$();\n",
+ "number", SimpleItoa(field->number()),
+ "capitalized_name", info->capitalized_name);
+ }
+ printer->Print(
+ "default:\n"
+ " throw new RuntimeException(\n"
+ " \"Invalid map field number: \" + number);\n");
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n"
+ "}\n");
+ printer->Print(
+ "@SuppressWarnings({\"rawtypes\"})\n"
+ "protected com.google.protobuf.MapField internalGetMutableMapField(\n"
+ " int number) {\n"
+ " switch (number) {\n");
+ printer->Indent();
+ printer->Indent();
+ for (int i = 0; i < map_fields.size(); ++i) {
+ const FieldDescriptor* field = map_fields[i];
+ const FieldGeneratorInfo* info =
+ context_->GetFieldGeneratorInfo(field);
+ printer->Print(
+ "case $number$:\n"
+ " return internalGetMutable$capitalized_name$();\n",
+ "number", SimpleItoa(field->number()),
+ "capitalized_name", info->capitalized_name);
+ }
+ printer->Print(
+ "default:\n"
+ " throw new RuntimeException(\n"
+ " \"Invalid map field number: \" + number);\n");
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n"
+ "}\n");
+ }
+ printer->Print(
+ "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+ " internalGetFieldAccessorTable() {\n"
+ " return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
+ " .ensureFieldAccessorsInitialized(\n"
+ " $classname$.class, $classname$.Builder.class);\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+ "identifier", UniqueFileScopeIdentifier(descriptor_));
+}
+
+// ===================================================================
+
+void MessageBuilderGenerator::
+GenerateCommonBuilderMethods(io::Printer* printer) {
+ printer->Print(
+ "// Construct using $classname$.newBuilder()\n"
+ "private Builder() {\n"
+ " maybeForceBuilderInitialization();\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "private Builder(\n"
+ " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
+ " super(parent);\n"
+ " maybeForceBuilderInitialization();\n"
+ "}\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "private void maybeForceBuilderInitialization() {\n"
+ " if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n");
+
+ printer->Indent();
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!descriptor_->field(i)->containing_oneof()) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateFieldBuilderInitializationCode(printer);
+ }
+ }
+ printer->Outdent();
+ printer->Outdent();
+
+ printer->Print(
+ " }\n"
+ "}\n");
+
+ printer->Print(
+ "public Builder clear() {\n"
+ " super.clear();\n");
+
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!descriptor_->field(i)->containing_oneof()) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateBuilderClearCode(printer);
+ }
+ }
+
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ printer->Print(
+ "$oneof_name$Case_ = 0;\n"
+ "$oneof_name$_ = null;\n",
+ "oneof_name", context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->name);
+ }
+
+ printer->Outdent();
+
+ printer->Print(
+ " return this;\n"
+ "}\n"
+ "\n");
+
+ printer->Print(
+ "public com.google.protobuf.Descriptors.Descriptor\n"
+ " getDescriptorForType() {\n"
+ " return $fileclass$.internal_$identifier$_descriptor;\n"
+ "}\n"
+ "\n",
+ "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+ "identifier", UniqueFileScopeIdentifier(descriptor_));
+
+ // LITE runtime implements this in GeneratedMessageLite.
+ printer->Print(
+ "public $classname$ getDefaultInstanceForType() {\n"
+ " return $classname$.getDefaultInstance();\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "public $classname$ build() {\n"
+ " $classname$ result = buildPartial();\n"
+ " if (!result.isInitialized()) {\n"
+ " throw newUninitializedMessageException(result);\n"
+ " }\n"
+ " return result;\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "public $classname$ buildPartial() {\n"
+ " $classname$ result = new $classname$(this);\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Indent();
+
+ int totalBuilderBits = 0;
+ int totalMessageBits = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const ImmutableFieldGenerator& field =
+ field_generators_.get(descriptor_->field(i));
+ totalBuilderBits += field.GetNumBitsForBuilder();
+ totalMessageBits += field.GetNumBitsForMessage();
+ }
+ int totalBuilderInts = (totalBuilderBits + 31) / 32;
+ int totalMessageInts = (totalMessageBits + 31) / 32;
+
+ if (GenerateHasBits(descriptor_)) {
+ // Local vars for from and to bit fields to avoid accessing the builder and
+ // message over and over for these fields. Seems to provide a slight
+ // perforamance improvement in micro benchmark and this is also what proto1
+ // code does.
+ for (int i = 0; i < totalBuilderInts; i++) {
+ printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+ for (int i = 0; i < totalMessageInts; i++) {
+ printer->Print("int to_$bit_field_name$ = 0;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+ }
+
+ // Output generation code for each field.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer);
+ }
+
+ if (GenerateHasBits(descriptor_)) {
+ // Copy the bit field results to the generated message
+ for (int i = 0; i < totalMessageInts; i++) {
+ printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+ }
+
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n",
+ "oneof_name", context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->name);
+ }
+
+ printer->Outdent();
+
+ printer->Print(
+ " onBuilt();\n");
+
+ printer->Print(
+ " return result;\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ // -----------------------------------------------------------------
+
+ if (HasGeneratedMethods(descriptor_)) {
+ printer->Print(
+ "public Builder mergeFrom(com.google.protobuf.Message other) {\n"
+ " if (other instanceof $classname$) {\n"
+ " return mergeFrom(($classname$)other);\n"
+ " } else {\n"
+ " super.mergeFrom(other);\n"
+ " return this;\n"
+ " }\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "public Builder mergeFrom($classname$ other) {\n"
+ // Optimization: If other is the default instance, we know none of its
+ // fields are set so we can skip the merge.
+ " if (other == $classname$.getDefaultInstance()) return this;\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!descriptor_->field(i)->containing_oneof()) {
+ field_generators_.get(
+ descriptor_->field(i)).GenerateMergingCode(printer);
+ }
+ }
+
+ // Merge oneof fields.
+ for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
+ printer->Print(
+ "switch (other.get$oneof_capitalized_name$Case()) {\n",
+ "oneof_capitalized_name",
+ context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->capitalized_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(
+ "case $field_name$: {\n",
+ "field_name",
+ ToUpper(field->name()));
+ printer->Indent();
+ field_generators_.get(field).GenerateMergingCode(printer);
+ printer->Print(
+ "break;\n");
+ printer->Outdent();
+ printer->Print(
+ "}\n");
+ }
+ printer->Print(
+ "case $cap_oneof_name$_NOT_SET: {\n"
+ " break;\n"
+ "}\n",
+ "cap_oneof_name",
+ ToUpper(context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->name));
+ printer->Outdent();
+ printer->Print(
+ "}\n");
+ }
+
+ printer->Outdent();
+
+ // if message type has extensions
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ " this.mergeExtensionFields(other);\n");
+ }
+
+ if (PreserveUnknownFields(descriptor_)) {
+ printer->Print(
+ " this.mergeUnknownFields(other.unknownFields);\n");
+ }
+
+ printer->Print(
+ " onChanged();\n");
+
+ printer->Print(
+ " return this;\n"
+ "}\n"
+ "\n");
+ }
+}
+
+// ===================================================================
+
+void MessageBuilderGenerator::
+GenerateBuilderParsingMethods(io::Printer* printer) {
+ printer->Print(
+ "public Builder mergeFrom(\n"
+ " com.google.protobuf.CodedInputStream input,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws java.io.IOException {\n"
+ " $classname$ parsedMessage = null;\n"
+ " try {\n"
+ " parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n"
+ " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
+ " parsedMessage = ($classname$) e.getUnfinishedMessage();\n"
+ " throw e;\n"
+ " } finally {\n"
+ " if (parsedMessage != null) {\n"
+ " mergeFrom(parsedMessage);\n"
+ " }\n"
+ " }\n"
+ " return this;\n"
+ "}\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+}
+
+// ===================================================================
+
+void MessageBuilderGenerator::GenerateIsInitialized(
+ io::Printer* printer) {
+ printer->Print(
+ "public final boolean isInitialized() {\n");
+ printer->Indent();
+
+ // Check that all required fields in this message are set.
+ // TODO(kenton): We can optimize this when we switch to putting all the
+ // "has" fields into a single bitfield.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+
+ if (field->is_required()) {
+ printer->Print(
+ "if (!has$name$()) {\n"
+ " return false;\n"
+ "}\n",
+ "name", info->capitalized_name);
+ }
+ }
+
+ // Now check that all embedded messages are initialized.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+ HasRequiredFields(field->message_type())) {
+ switch (field->label()) {
+ case FieldDescriptor::LABEL_REQUIRED:
+ printer->Print(
+ "if (!get$name$().isInitialized()) {\n"
+ " return false;\n"
+ "}\n",
+ "type", name_resolver_->GetImmutableClassName(
+ field->message_type()),
+ "name", info->capitalized_name);
+ break;
+ case FieldDescriptor::LABEL_OPTIONAL:
+ if (!SupportFieldPresence(descriptor_->file()) &&
+ field->containing_oneof() != NULL) {
+ const OneofDescriptor* oneof = field->containing_oneof();
+ const OneofGeneratorInfo* oneof_info =
+ context_->GetOneofGeneratorInfo(oneof);
+ printer->Print(
+ "if ($oneof_name$Case_ == $field_number$) {\n",
+ "oneof_name", oneof_info->name,
+ "field_number", SimpleItoa(field->number()));
+ } else {
+ printer->Print(
+ "if (has$name$()) {\n",
+ "name", info->capitalized_name);
+ }
+ printer->Print(
+ " if (!get$name$().isInitialized()) {\n"
+ " return false;\n"
+ " }\n"
+ "}\n",
+ "name", info->capitalized_name);
+ break;
+ case FieldDescriptor::LABEL_REPEATED:
+ if (IsMapEntry(field->message_type())) {
+ printer->Print(
+ "for ($type$ item : get$name$().values()) {\n"
+ " if (!item.isInitialized()) {\n"
+ " return false;\n"
+ " }\n"
+ "}\n",
+ "type", MapValueImmutableClassdName(field->message_type(),
+ name_resolver_),
+ "name", info->capitalized_name);
+ } else {
+ printer->Print(
+ "for (int i = 0; i < get$name$Count(); i++) {\n"
+ " if (!get$name$(i).isInitialized()) {\n"
+ " return false;\n"
+ " }\n"
+ "}\n",
+ "type", name_resolver_->GetImmutableClassName(
+ field->message_type()),
+ "name", info->capitalized_name);
+ }
+ break;
+ }
+ }
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "if (!extensionsAreInitialized()) {\n"
+ " return false;\n"
+ "}\n");
+ }
+
+ printer->Outdent();
+
+ printer->Print(
+ " return true;\n"
+ "}\n"
+ "\n");
+}
+
+// ===================================================================
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_message_builder.h b/src/google/protobuf/compiler/java/java_message_builder.h
new file mode 100644
index 00000000..015ea062
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_builder.h
@@ -0,0 +1,86 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__
+
+#include <string>
+#include <map>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ class ClassNameResolver; // name_resolver.h
+ }
+ }
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class MessageBuilderGenerator {
+ public:
+ explicit MessageBuilderGenerator(const Descriptor* descriptor,
+ Context* context);
+ virtual ~MessageBuilderGenerator();
+
+ virtual void Generate(io::Printer* printer);
+
+ private:
+ void GenerateCommonBuilderMethods(io::Printer* printer);
+ void GenerateDescriptorMethods(io::Printer* printer);
+ void GenerateBuilderParsingMethods(io::Printer* printer);
+ void GenerateIsInitialized(io::Printer* printer);
+
+ const Descriptor* descriptor_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+ FieldGeneratorMap<ImmutableFieldGenerator> field_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__
diff --git a/src/google/protobuf/compiler/java/java_message_builder_lite.cc b/src/google/protobuf/compiler/java/java_message_builder_lite.cc
new file mode 100644
index 00000000..8719d00d
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_builder_lite.cc
@@ -0,0 +1,192 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_message_builder_lite.h>
+
+#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 <vector>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum.h>
+#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_generator_factory.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+bool GenerateHasBits(const Descriptor* descriptor) {
+ return SupportFieldPresence(descriptor->file()) ||
+ HasRepeatedFields(descriptor);
+}
+
+string MapValueImmutableClassdName(const Descriptor* descriptor,
+ ClassNameResolver* name_resolver) {
+ const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
+ return name_resolver->GetImmutableClassName(value_field->message_type());
+}
+} // namespace
+
+MessageBuilderLiteGenerator::MessageBuilderLiteGenerator(
+ const Descriptor* descriptor, Context* context)
+ : descriptor_(descriptor), context_(context),
+ name_resolver_(context->GetNameResolver()),
+ field_generators_(descriptor, context_) {
+ GOOGLE_CHECK_EQ(
+ FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+}
+
+MessageBuilderLiteGenerator::~MessageBuilderLiteGenerator() {}
+
+void MessageBuilderLiteGenerator::
+Generate(io::Printer* printer) {
+ WriteMessageDocComment(printer, descriptor_);
+ printer->Print(
+ "public static final class Builder extends\n"
+ " com.google.protobuf.GeneratedMessageLite.$extendible$Builder<\n"
+ " $classname$, Builder> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "extra_interfaces", ExtraBuilderInterfaces(descriptor_),
+ "extendible",
+ descriptor_->extension_range_count() > 0 ? "Extendable" : "");
+ printer->Indent();
+
+ GenerateCommonBuilderMethods(printer);
+
+ // oneof
+ map<string, string> vars;
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ vars["oneof_name"] = context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->name;
+ vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->capitalized_name;
+ vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+
+ // oneofCase() and clearOneof()
+ printer->Print(vars,
+ "public $oneof_capitalized_name$Case\n"
+ " get$oneof_capitalized_name$Case() {\n"
+ " return instance.get$oneof_capitalized_name$Case();\n"
+ "}\n"
+ "\n"
+ "public Builder clear$oneof_capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$oneof_capitalized_name$();\n"
+ " return this;\n"
+ "}\n"
+ "\n");
+ }
+
+ 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))
+ .GetNumBitsForBuilder();
+ }
+ int totalInts = (totalBits + 31) / 32;
+ for (int i = 0; i < totalInts; i++) {
+ printer->Print("private int $bit_field_name$;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+ }
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("\n");
+ field_generators_.get(descriptor_->field(i))
+ .GenerateBuilderMembers(printer);
+ }
+
+ 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",
+ "full_name", descriptor_->full_name());
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+// ===================================================================
+
+void MessageBuilderLiteGenerator::
+GenerateCommonBuilderMethods(io::Printer* printer) {
+ printer->Print(
+ "// Construct using $classname$.newBuilder()\n"
+ "private Builder() {\n"
+ " super(DEFAULT_INSTANCE);\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+}
+
+// ===================================================================
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_message_builder_lite.h b/src/google/protobuf/compiler/java/java_message_builder_lite.h
new file mode 100644
index 00000000..8597b2e6
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_builder_lite.h
@@ -0,0 +1,83 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__
+
+#include <string>
+#include <map>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ class ClassNameResolver; // name_resolver.h
+ }
+ }
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class MessageBuilderLiteGenerator {
+ public:
+ explicit MessageBuilderLiteGenerator(const Descriptor* descriptor,
+ Context* context);
+ virtual ~MessageBuilderLiteGenerator();
+
+ virtual void Generate(io::Printer* printer);
+
+ private:
+ void GenerateCommonBuilderMethods(io::Printer* printer);
+
+ const Descriptor* descriptor_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+ FieldGeneratorMap<ImmutableFieldLiteGenerator> field_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index 538f1248..b180b4a7 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -157,11 +157,9 @@ GenerateInterfaceMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$$type$ get$capitalized_name$();\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n");
}
void ImmutableMessageFieldGenerator::
@@ -182,14 +180,12 @@ GenerateMembers(io::Printer* printer) const {
" return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
"}\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder "
- "get$capitalized_name$OrBuilder() {\n"
- " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
- "}\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder "
+ "get$capitalized_name$OrBuilder() {\n"
+ " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
+ "}\n");
} else {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -202,14 +198,12 @@ GenerateMembers(io::Printer* printer) const {
" return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
"}\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder "
- "get$capitalized_name$OrBuilder() {\n"
- " return get$capitalized_name$();\n"
- "}\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder "
+ "get$capitalized_name$OrBuilder() {\n"
+ " return get$capitalized_name$();\n"
+ "}\n");
}
}
@@ -217,19 +211,15 @@ void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition(
io::Printer* printer,
const char* regular_case,
const char* nested_builder_case) const {
- if (HasNestedBuilders(descriptor_->containing_type())) {
- printer->Print(variables_, "if ($name$Builder_ == null) {\n");
- printer->Indent();
- printer->Print(variables_, regular_case);
- printer->Outdent();
- printer->Print("} else {\n");
- printer->Indent();
- printer->Print(variables_, nested_builder_case);
- printer->Outdent();
- printer->Print("}\n");
- } else {
- printer->Print(variables_, regular_case);
- }
+ printer->Print(variables_, "if ($name$Builder_ == null) {\n");
+ printer->Indent();
+ printer->Print(variables_, regular_case);
+ printer->Outdent();
+ printer->Print("} else {\n");
+ printer->Indent();
+ printer->Print(variables_, nested_builder_case);
+ printer->Outdent();
+ printer->Print("}\n");
}
void ImmutableMessageFieldGenerator::PrintNestedBuilderFunction(
@@ -260,14 +250,12 @@ GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
"private $type$ $name$_ = null;\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- printer->Print(variables_,
+ printer->Print(variables_,
// If this builder is non-null, it is used and the other fields are
// ignored.
"private com.google.protobuf.SingleFieldBuilder<\n"
" $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
"\n");
- }
// The comments above the methods below are based on a hypothetical
// field of type "Field" called "Field".
@@ -368,40 +356,38 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$clear_has_field_bit_builder$\n"
"return this;\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
- " $set_has_field_bit_builder$\n"
- " $on_changed$\n"
- " return get$capitalized_name$FieldBuilder().getBuilder();\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
- " if ($name$Builder_ != null) {\n"
- " return $name$Builder_.getMessageOrBuilder();\n"
- " } else {\n"
- " return $name$_ == null ?\n"
- " $type$.getDefaultInstance() : $name$_;\n"
- " }\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "private com.google.protobuf.SingleFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> \n"
- " get$capitalized_name$FieldBuilder() {\n"
- " if ($name$Builder_ == null) {\n"
- " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder>(\n"
- " get$capitalized_name$(),\n"
- " getParentForChildren(),\n"
- " isClean());\n"
- " $name$_ = null;\n"
- " }\n"
- " return $name$Builder_;\n"
- "}\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
+ " $set_has_field_bit_builder$\n"
+ " $on_changed$\n"
+ " return get$capitalized_name$FieldBuilder().getBuilder();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+ " if ($name$Builder_ != null) {\n"
+ " return $name$Builder_.getMessageOrBuilder();\n"
+ " } else {\n"
+ " return $name$_ == null ?\n"
+ " $type$.getDefaultInstance() : $name$_;\n"
+ " }\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private com.google.protobuf.SingleFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> \n"
+ " get$capitalized_name$FieldBuilder() {\n"
+ " if ($name$Builder_ == null) {\n"
+ " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder>(\n"
+ " get$capitalized_name$(),\n"
+ " getParentForChildren(),\n"
+ " isClean());\n"
+ " $name$_ = null;\n"
+ " }\n"
+ " return $name$Builder_;\n"
+ "}\n");
}
void ImmutableMessageFieldGenerator::
@@ -557,16 +543,14 @@ GenerateMembers(io::Printer* printer) const {
" return $type$.getDefaultInstance();\n"
"}\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
- " if ($has_oneof_case_message$) {\n"
- " return ($type$) $oneof_name$_;\n"
- " }\n"
- " return $type$.getDefaultInstance();\n"
- "}\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($type$) $oneof_name$_;\n"
+ " }\n"
+ " return $type$.getDefaultInstance();\n"
+ "}\n");
}
void ImmutableMessageOneofFieldGenerator::
@@ -574,14 +558,12 @@ GenerateBuilderMembers(io::Printer* printer) const {
// When using nested-builders, the code initially works just like the
// non-nested builder case. It only creates a nested builder lazily on
// demand and then forever delegates to it after creation.
- if (HasNestedBuilders(descriptor_->containing_type())) {
- printer->Print(variables_,
- // If this builder is non-null, it is used and the other fields are
- // ignored.
- "private com.google.protobuf.SingleFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
- "\n");
- }
+ printer->Print(variables_,
+ // If this builder is non-null, it is used and the other fields are
+ // ignored.
+ "private com.google.protobuf.SingleFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
+ "\n");
// The comments above the methods below are based on a hypothetical
// field of type "Field" called "Field".
@@ -683,44 +665,43 @@ GenerateBuilderMembers(io::Printer* printer) const {
"return this;\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
- " return get$capitalized_name$FieldBuilder().getBuilder();\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
- " if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n"
- " return $name$Builder_.getMessageOrBuilder();\n"
- " } else {\n"
- " if ($has_oneof_case_message$) {\n"
- " return ($type$) $oneof_name$_;\n"
- " }\n"
- " return $type$.getDefaultInstance();\n"
- " }\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "private com.google.protobuf.SingleFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> \n"
- " get$capitalized_name$FieldBuilder() {\n"
- " if ($name$Builder_ == null) {\n"
- " if (!($has_oneof_case_message$)) {\n"
- " $oneof_name$_ = $type$.getDefaultInstance();\n"
- " }\n"
- " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder>(\n"
- " ($type$) $oneof_name$_,\n"
- " getParentForChildren(),\n"
- " isClean());\n"
- " $oneof_name$_ = null;\n"
- " }\n"
- " $set_oneof_case_message$;\n"
- " return $name$Builder_;\n"
- "}\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
+ " return get$capitalized_name$FieldBuilder().getBuilder();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+ " if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n"
+ " return $name$Builder_.getMessageOrBuilder();\n"
+ " } else {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($type$) $oneof_name$_;\n"
+ " }\n"
+ " return $type$.getDefaultInstance();\n"
+ " }\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private com.google.protobuf.SingleFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> \n"
+ " get$capitalized_name$FieldBuilder() {\n"
+ " if ($name$Builder_ == null) {\n"
+ " if (!($has_oneof_case_message$)) {\n"
+ " $oneof_name$_ = $type$.getDefaultInstance();\n"
+ " }\n"
+ " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder>(\n"
+ " ($type$) $oneof_name$_,\n"
+ " getParentForChildren(),\n"
+ " isClean());\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ " $set_oneof_case_message$;\n"
+ " $on_changed$;\n"
+ " return $name$Builder_;\n"
+ "}\n");
}
void ImmutableMessageOneofFieldGenerator::
@@ -830,16 +811,15 @@ GenerateInterfaceMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$int get$capitalized_name$Count();\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$java.util.List<? extends $type$OrBuilder> \n"
- " get$capitalized_name$OrBuilderList();\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n"
- " int index);\n");
- }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<? extends $type$OrBuilder> \n"
+ " get$capitalized_name$OrBuilderList();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n"
+ " int index);\n");
}
void RepeatedImmutableMessageFieldGenerator::
@@ -881,19 +861,15 @@ void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderCondition(
io::Printer* printer,
const char* regular_case,
const char* nested_builder_case) const {
- if (HasNestedBuilders(descriptor_->containing_type())) {
- printer->Print(variables_, "if ($name$Builder_ == null) {\n");
- printer->Indent();
- printer->Print(variables_, regular_case);
- printer->Outdent();
- printer->Print("} else {\n");
- printer->Indent();
- printer->Print(variables_, nested_builder_case);
- printer->Outdent();
- printer->Print("}\n");
- } else {
- printer->Print(variables_, regular_case);
- }
+ printer->Print(variables_, "if ($name$Builder_ == null) {\n");
+ printer->Indent();
+ printer->Print(variables_, regular_case);
+ printer->Outdent();
+ printer->Print("} else {\n");
+ printer->Indent();
+ printer->Print(variables_, nested_builder_case);
+ printer->Outdent();
+ printer->Print("}\n");
}
void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderFunction(
@@ -941,14 +917,12 @@ GenerateBuilderMembers(io::Printer* printer) const {
"}\n"
"\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- printer->Print(variables_,
- // If this builder is non-null, it is used and the other fields are
- // ignored.
- "private com.google.protobuf.RepeatedFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
- "\n");
- }
+ printer->Print(variables_,
+ // If this builder is non-null, it is used and the other fields are
+ // ignored.
+ "private com.google.protobuf.RepeatedFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
+ "\n");
// The comments above the methods below are based on a hypothetical
// repeated field of type "Field" called "RepeatedField".
@@ -1115,70 +1089,68 @@ GenerateBuilderMembers(io::Printer* printer) const {
"return this;\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
- " int index) {\n"
- " return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
- "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
+ " int index) {\n"
+ " return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
+ "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
- " int index) {\n"
- " if ($name$Builder_ == null) {\n"
- " return $name$_.get(index);"
- " } else {\n"
- " return $name$Builder_.getMessageOrBuilder(index);\n"
- " }\n"
- "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+ " int index) {\n"
+ " if ($name$Builder_ == null) {\n"
+ " return $name$_.get(index);"
+ " } else {\n"
+ " return $name$Builder_.getMessageOrBuilder(index);\n"
+ " }\n"
+ "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
- " get$capitalized_name$OrBuilderList() {\n"
- " if ($name$Builder_ != null) {\n"
- " return $name$Builder_.getMessageOrBuilderList();\n"
- " } else {\n"
- " return java.util.Collections.unmodifiableList($name$_);\n"
- " }\n"
- "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+ " get$capitalized_name$OrBuilderList() {\n"
+ " if ($name$Builder_ != null) {\n"
+ " return $name$Builder_.getMessageOrBuilderList();\n"
+ " } else {\n"
+ " return java.util.Collections.unmodifiableList($name$_);\n"
+ " }\n"
+ "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
- " return get$capitalized_name$FieldBuilder().addBuilder(\n"
- " $type$.getDefaultInstance());\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
- " int index) {\n"
- " return get$capitalized_name$FieldBuilder().addBuilder(\n"
- " index, $type$.getDefaultInstance());\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public java.util.List<$type$.Builder> \n"
- " get$capitalized_name$BuilderList() {\n"
- " return get$capitalized_name$FieldBuilder().getBuilderList();\n"
- "}\n"
- "private com.google.protobuf.RepeatedFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> \n"
- " get$capitalized_name$FieldBuilder() {\n"
- " if ($name$Builder_ == null) {\n"
- " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder>(\n"
- " $name$_,\n"
- " $get_mutable_bit_builder$,\n"
- " getParentForChildren(),\n"
- " isClean());\n"
- " $name$_ = null;\n"
- " }\n"
- " return $name$Builder_;\n"
- "}\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
+ " return get$capitalized_name$FieldBuilder().addBuilder(\n"
+ " $type$.getDefaultInstance());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
+ " int index) {\n"
+ " return get$capitalized_name$FieldBuilder().addBuilder(\n"
+ " index, $type$.getDefaultInstance());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$type$.Builder> \n"
+ " get$capitalized_name$BuilderList() {\n"
+ " return get$capitalized_name$FieldBuilder().getBuilderList();\n"
+ "}\n"
+ "private com.google.protobuf.RepeatedFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> \n"
+ " get$capitalized_name$FieldBuilder() {\n"
+ " if ($name$Builder_ == null) {\n"
+ " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder>(\n"
+ " $name$_,\n"
+ " $get_mutable_bit_builder$,\n"
+ " getParentForChildren(),\n"
+ " isClean());\n"
+ " $name$_ = null;\n"
+ " }\n"
+ " return $name$Builder_;\n"
+ "}\n");
}
void RepeatedImmutableMessageFieldGenerator::
diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.cc b/src/google/protobuf/compiler/java/java_message_field_lite.cc
new file mode 100644
index 00000000..8332202c
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc
@@ -0,0 +1,944 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_message_field_lite.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/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+void SetMessageVariables(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ map<string, string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+
+ (*variables)["type"] =
+ name_resolver->GetImmutableClassName(descriptor->message_type());
+ (*variables)["mutable_type"] =
+ name_resolver->GetMutableClassName(descriptor->message_type());
+ (*variables)["group_or_message"] =
+ (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ?
+ "Group" : "Message";
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] = descriptor->options().deprecated()
+ ? "@java.lang.Deprecated " : "";
+ (*variables)["on_changed"] =
+ HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+ if (SupportFieldPresence(descriptor->file())) {
+ // For singular messages and builders, one bit is used for the hasField bit.
+ (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+ // Note that these have a trailing ";".
+ (*variables)["set_has_field_bit_message"] =
+ GenerateSetBit(messageBitIndex) + ";";
+ (*variables)["clear_has_field_bit_message"] =
+ GenerateClearBit(messageBitIndex) + ";";
+
+ (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+ } else {
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["clear_has_field_bit_message"] = "";
+
+ (*variables)["is_field_present_message"] =
+ (*variables)["name"] + "_ != null";
+ }
+
+ // For repeated builders, the underlying list tracks mutability state.
+ (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
+
+ (*variables)["get_has_field_bit_from_local"] =
+ GenerateGetBitFromLocal(builderBitIndex);
+ (*variables)["set_has_field_bit_to_local"] =
+ GenerateSetBitToLocal(messageBitIndex);
+}
+
+} // namespace
+
+// ===================================================================
+
+ImmutableMessageFieldLiteGenerator::
+ImmutableMessageFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+ImmutableMessageFieldLiteGenerator::~ImmutableMessageFieldLiteGenerator() {}
+
+int ImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 1;
+}
+
+int ImmutableMessageFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ // TODO(jonp): In the future, consider having a method specific to the
+ // interface so that builders can choose dynamically to either return a
+ // message or a nested builder, so that asking for the interface doesn't
+ // cause a message to ever be built.
+ if (SupportFieldPresence(descriptor_->file()) ||
+ descriptor_->containing_oneof() == NULL) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$boolean has$capitalized_name$();\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private $type$ $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
+ "}\n");
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $name$_ != null;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
+ "}\n");
+ }
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " $name$_ = value;\n"
+ " $set_has_field_bit_message$\n"
+ " }\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " $name$_ = builderForValue.build();\n"
+ " $set_has_field_bit_message$\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void merge$capitalized_name$($type$ value) {\n"
+ " if ($name$_ != null &&\n"
+ " $name$_ != $type$.getDefaultInstance()) {\n"
+ " $name$_ =\n"
+ " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
+ " } else {\n"
+ " $name$_ = value;\n"
+ " }\n"
+ " $set_has_field_bit_message$\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {"
+ " $name$_ = null;\n"
+ " $clear_has_field_bit_message$\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ // The comments above the methods below are based on a hypothetical
+ // field of type "Field" called "Field".
+
+ // boolean hasField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+
+ // Field getField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ " }\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.merge$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ printer->Print(variables_,
+ "get$capitalized_name$FieldBuilder();\n");
+ }
+}
+
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (other.has$capitalized_name$()) {\n"
+ " merge$capitalized_name$(other.get$capitalized_name$());\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ // noop for scalars
+}
+
+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");
+
+ if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(variables_,
+ "$name$_ = input.readGroup($number$, $type$.PARSER,\n"
+ " extensionRegistry);\n");
+ } else {
+ printer->Print(variables_,
+ "$name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n");
+ }
+
+ printer->Print(variables_,
+ "if (subBuilder != null) {\n"
+ " subBuilder.mergeFrom($name$_);\n"
+ " $name$_ = subBuilder.buildPartial();\n"
+ "}\n"
+ "$set_has_field_bit_message$\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ // noop for messages.
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " output.write$group_or_message$($number$, get$capitalized_name$());\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .compute$group_or_message$Size($number$, get$capitalized_name$());\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$()\n"
+ " .equals(other.get$capitalized_name$());\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n"
+ "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+}
+
+string ImmutableMessageFieldLiteGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+// ===================================================================
+
+ImmutableMessageOneofFieldLiteGenerator::
+ImmutableMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : ImmutableMessageFieldLiteGenerator(
+ descriptor, messageBitIndex, builderBitIndex, context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableMessageOneofFieldLiteGenerator::
+~ImmutableMessageOneofFieldLiteGenerator() {}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($type$) $oneof_name$_;\n"
+ " }\n"
+ " return $type$.getDefaultInstance();\n"
+ "}\n");
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " $oneof_name$_ = value;\n"
+ " $set_oneof_case_message$;\n"
+ "}\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " $oneof_name$_ = builderForValue.build();\n"
+ " $set_oneof_case_message$;\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void merge$capitalized_name$($type$ value) {\n"
+ " if ($has_oneof_case_message$ &&\n"
+ " $oneof_name$_ != $type$.getDefaultInstance()) {\n"
+ " $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n"
+ " .mergeFrom(value).buildPartial();\n"
+ " } else {\n"
+ " $oneof_name$_ = value;\n"
+ " }\n"
+ " $set_oneof_case_message$;\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ "}\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ // The comments above the methods below are based on a hypothetical
+ // field of type "Field" called "Field".
+
+ if (SupportFieldPresence(descriptor_->file())) {
+ // boolean hasField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ }
+
+ // Field getField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.merge$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "merge$capitalized_name$(other.get$capitalized_name$());\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$type$.Builder subBuilder = null;\n"
+ "if ($has_oneof_case_message$) {\n"
+ " subBuilder = (($type$) $oneof_name$_).toBuilder();\n"
+ "}\n");
+
+ if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(variables_,
+ "$oneof_name$_ = input.readGroup($number$, $type$.PARSER,\n"
+ " extensionRegistry);\n");
+ } else {
+ printer->Print(variables_,
+ "$oneof_name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n");
+ }
+
+ printer->Print(variables_,
+ "if (subBuilder != null) {\n"
+ " subBuilder.mergeFrom(($type$) $oneof_name$_);\n"
+ " $oneof_name$_ = subBuilder.buildPartial();\n"
+ "}\n");
+ printer->Print(variables_,
+ "$set_oneof_case_message$;\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " output.write$group_or_message$($number$, ($type$) $oneof_name$_);\n"
+ "}\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .compute$group_or_message$Size($number$, ($type$) $oneof_name$_);\n"
+ "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutableMessageFieldLiteGenerator::
+RepeatedImmutableMessageFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+RepeatedImmutableMessageFieldLiteGenerator::
+~RepeatedImmutableMessageFieldLiteGenerator() {}
+
+int RepeatedImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+int RepeatedImmutableMessageFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ // TODO(jonp): In the future, consider having methods specific to the
+ // interface so that builders can choose dynamically to either return a
+ // message or a nested builder, so that asking for the interface doesn't
+ // cause a message to ever be built.
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<$type$> \n"
+ " get$capitalized_name$List();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$(int index);\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private com.google.protobuf.Internal.ProtobufList<$type$> $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+ " return $name$_;\n" // note: unmodifiable list
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+ " get$capitalized_name$OrBuilderList() {\n"
+ " return $name$_;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+ " int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+
+ printer->Print(variables_,
+ "private void ensure$capitalized_name$IsMutable() {\n"
+ " if (!$is_mutable$) {\n"
+ " $name$_ = newProtobufList($name$_);\n"
+ " }\n"
+ "}\n"
+ "\n");
+
+ // Builder setRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, value);\n"
+ "}\n");
+
+ // Builder setRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, builderForValue.build());\n"
+ "}\n");
+
+ // Builder addRepeatedField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value);\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(index, value);\n"
+ "}\n");
+ // Builder addRepeatedField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(builderForValue.build());\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(index, builderForValue.build());\n"
+ "}\n");
+
+ // Builder addAllRepeatedField(Iterable<Field> values)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " com.google.protobuf.AbstractMessageLite.addAll(\n"
+ " values, $name$_);\n"
+ "}\n");
+
+ // Builder clearAllRepeatedField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $name$_ = emptyProtobufList();\n"
+ "}\n");
+
+ // Builder removeRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void remove$capitalized_name$(int index) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.remove(index);\n"
+ "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ // The comments above the methods below are based on a hypothetical
+ // repeated field of type "Field" called "RepeatedField".
+
+ // List<Field> getRepeatedFieldList()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+ " return java.util.Collections.unmodifiableList(\n"
+ " instance.get$capitalized_name$List());\n"
+ "}\n");
+
+ // int getRepeatedFieldCount()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return instance.get$capitalized_name$Count();\n"
+ "}");
+
+ // Field getRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+ " return instance.get$capitalized_name$(index);\n"
+ "}\n");
+
+ // Builder setRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder setRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addRepeatedField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+ // Builder addRepeatedField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(index, builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addAllRepeatedField(Iterable<Field> values)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$(values);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder clearAllRepeatedField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder removeRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder remove$capitalized_name$(int index) {\n"
+ " copyOnWrite();\n"
+ " instance.remove$capitalized_name$(index);\n"
+ " return this;\n"
+ "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "get$capitalized_name$FieldBuilder();\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = emptyProtobufList();\n");
+}
+
+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");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_.makeImmutable();\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!$is_mutable$) {\n"
+ " $name$_ = newProtobufList();\n"
+ "}\n");
+
+ if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(variables_,
+ "$name$_.add(input.readGroup($number$, $type$.PARSER,\n"
+ " extensionRegistry));\n");
+ } else {
+ printer->Print(variables_,
+ "$name$_.add(input.readMessage($type$.PARSER, extensionRegistry));\n");
+ }
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_mutable$) {\n"
+ " $name$_.makeImmutable();\n"
+ "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.write$group_or_message$($number$, $name$_.get(i));\n"
+ "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .compute$group_or_message$Size($number$, $name$_.get(i));\n"
+ "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$List()\n"
+ " .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (get$capitalized_name$Count() > 0) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+ "}\n");
+}
+
+string RepeatedImmutableMessageFieldLiteGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.h b/src/google/protobuf/compiler/java/java_message_field_lite.h
new file mode 100644
index 00000000..ae26c06a
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.h
@@ -0,0 +1,157 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ class ClassNameResolver; // name_resolver.h
+ }
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator {
+ public:
+ explicit ImmutableMessageFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableMessageFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ int GetNumBitsForMessage() const;
+ int GetNumBitsForBuilder() const;
+ void GenerateInterfaceMembers(io::Printer* printer) const;
+ 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 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldLiteGenerator);
+};
+
+class ImmutableMessageOneofFieldLiteGenerator
+ : public ImmutableMessageFieldLiteGenerator {
+ public:
+ ImmutableMessageOneofFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableMessageOneofFieldLiteGenerator();
+
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutableMessageFieldLiteGenerator
+ : public ImmutableFieldLiteGenerator {
+ public:
+ explicit RepeatedImmutableMessageFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~RepeatedImmutableMessageFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ int GetNumBitsForMessage() const;
+ int GetNumBitsForBuilder() const;
+ void GenerateInterfaceMembers(io::Printer* printer) const;
+ 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 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc
new file mode 100644
index 00000000..3accee92
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -0,0 +1,1174 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_message_lite.h>
+
+#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 <vector>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum.h>
+#include <google/protobuf/compiler/java/java_extension.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>
+#include <google/protobuf/compiler/java/java_message_builder_lite.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+bool GenerateHasBits(const Descriptor* descriptor) {
+ return SupportFieldPresence(descriptor->file()) ||
+ HasRepeatedFields(descriptor);
+}
+
+string MapValueImmutableClassdName(const Descriptor* descriptor,
+ ClassNameResolver* name_resolver) {
+ const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
+ return name_resolver->GetImmutableClassName(value_field->message_type());
+}
+} // namespace
+
+// ===================================================================
+ImmutableMessageLiteGenerator::ImmutableMessageLiteGenerator(
+ const Descriptor* descriptor, Context* context)
+ : MessageGenerator(descriptor), context_(context),
+ name_resolver_(context->GetNameResolver()),
+ field_generators_(descriptor, context_) {
+ GOOGLE_CHECK_EQ(
+ FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+}
+
+ImmutableMessageLiteGenerator::~ImmutableMessageLiteGenerator() {}
+
+void ImmutableMessageLiteGenerator::GenerateStaticVariables(
+ io::Printer* printer) {
+ // Generate static members for all nested types.
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // TODO(kenton): Reuse MessageGenerator objects?
+ ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+ .GenerateStaticVariables(printer);
+ }
+}
+
+int ImmutableMessageLiteGenerator::GenerateStaticVariableInitializers(
+ io::Printer* printer) {
+ int bytecode_estimate = 0;
+ // Generate static member initializers for all nested types.
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // TODO(kenton): Reuse MessageGenerator objects?
+ bytecode_estimate +=
+ ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+ .GenerateStaticVariableInitializers(printer);
+ }
+ return bytecode_estimate;
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) {
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "public interface $classname$OrBuilder extends \n"
+ " $extra_interfaces$\n"
+ " com.google.protobuf.GeneratedMessageLite.\n"
+ " ExtendableMessageOrBuilder<\n"
+ " $classname$, $classname$.Builder> {\n",
+ "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+ "classname", descriptor_->name());
+ } else {
+ printer->Print(
+ "public interface $classname$OrBuilder extends\n"
+ " $extra_interfaces$\n"
+ " com.google.protobuf.MessageLiteOrBuilder {\n",
+ "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+ "classname", descriptor_->name());
+ }
+
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("\n");
+ field_generators_.get(descriptor_->field(i))
+ .GenerateInterfaceMembers(printer);
+ }
+ printer->Outdent();
+
+ printer->Print("}\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
+ bool is_own_file =
+ descriptor_->containing_type() == NULL &&
+ MultipleJavaFiles(descriptor_->file(), /* immutable = */ true);
+
+ map<string, string> variables;
+ variables["static"] = is_own_file ? " " : " static ";
+ variables["classname"] = descriptor_->name();
+ variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
+
+ WriteMessageDocComment(printer, descriptor_);
+
+ // The builder_type stores the super type name of the nested Builder class.
+ string builder_type;
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(variables,
+ "public $static$final class $classname$ extends\n"
+ " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
+ " $classname$, $classname$.Builder> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n");
+ builder_type = strings::Substitute(
+ "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>",
+ name_resolver_->GetImmutableClassName(descriptor_));
+ } else {
+ printer->Print(variables,
+ "public $static$final class $classname$ extends\n"
+ " com.google.protobuf.GeneratedMessageLite<\n"
+ " $classname$, $classname$.Builder> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n");
+
+ builder_type = "com.google.protobuf.GeneratedMessageLite.Builder";
+ }
+ printer->Indent();
+
+ GenerateParsingConstructor(printer);
+
+ // Nested types
+ for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+ EnumGenerator(descriptor_->enum_type(i), true, context_)
+ .Generate(printer);
+ }
+
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // Don't generate Java classes for map entry messages.
+ if (IsMapEntry(descriptor_->nested_type(i))) continue;
+ ImmutableMessageLiteGenerator messageGenerator(
+ descriptor_->nested_type(i), context_);
+ messageGenerator.GenerateInterface(printer);
+ messageGenerator.Generate(printer);
+ }
+
+ 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 < totalInts; i++) {
+ printer->Print("private int $bit_field_name$;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+ }
+
+ // oneof
+ map<string, string> vars;
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ vars["oneof_name"] = context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->name;
+ vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->capitalized_name;
+ vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+ // oneofCase_ and oneof_
+ printer->Print(vars,
+ "private int $oneof_name$Case_ = 0;\n"
+ "private java.lang.Object $oneof_name$_;\n");
+ // OneofCase enum
+ printer->Print(vars,
+ "public enum $oneof_capitalized_name$Case\n"
+ " implements com.google.protobuf.Internal.EnumLite {\n");
+ 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(
+ "$field_name$($field_number$),\n",
+ "field_name",
+ ToUpper(field->name()),
+ "field_number",
+ SimpleItoa(field->number()));
+ }
+ printer->Print(
+ "$cap_oneof_name$_NOT_SET(0);\n",
+ "cap_oneof_name",
+ ToUpper(vars["oneof_name"]));
+ printer->Print(vars,
+ "private int value = 0;\n"
+ "private $oneof_capitalized_name$Case(int value) {\n"
+ " this.value = value;\n"
+ "}\n");
+ printer->Print(vars,
+ "public static $oneof_capitalized_name$Case valueOf(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);
+ printer->Print(
+ " case $field_number$: return $field_name$;\n",
+ "field_number",
+ SimpleItoa(field->number()),
+ "field_name",
+ ToUpper(field->name()));
+ }
+ 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"
+ " }\n"
+ "}\n"
+ "public int getNumber() {\n"
+ " return this.value;\n"
+ "}\n",
+ "cap_oneof_name", ToUpper(vars["oneof_name"]));
+ printer->Outdent();
+ printer->Print("};\n\n");
+ // oneofCase()
+ printer->Print(vars,
+ "public $oneof_capitalized_name$Case\n"
+ "get$oneof_capitalized_name$Case() {\n"
+ " return $oneof_capitalized_name$Case.valueOf(\n"
+ " $oneof_name$Case_);\n"
+ "}\n"
+ "\n"
+ "private void clear$oneof_capitalized_name$() {\n"
+ " $oneof_name$Case_ = 0;\n"
+ " $oneof_name$_ = null;\n"
+ "}\n"
+ "\n");
+ }
+
+ // Fields
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("public static final int $constant_name$ = $number$;\n",
+ "constant_name", FieldConstantName(descriptor_->field(i)),
+ "number", SimpleItoa(descriptor_->field(i)->number()));
+ field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
+ printer->Print("\n");
+ }
+
+ GenerateMessageSerializationMethods(printer);
+
+ if (HasEqualsAndHashCode(descriptor_)) {
+ GenerateEqualsAndHashCode(printer);
+ }
+
+
+ GenerateParseFromMethods(printer);
+ GenerateBuilder(printer);
+
+ if (HasRequiredFields(descriptor_)) {
+ // Memoizes whether the protocol buffer is fully initialized (has all
+ // required fields). -1 means not yet computed. 0 means false and 1 means
+ // true.
+ printer->Print(
+ "private byte memoizedIsInitialized = -1;\n");
+ }
+
+ printer->Print(
+ "protected final Object dynamicMethod(\n"
+ " com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n"
+ " Object... args) {\n"
+ " switch (method) {\n"
+ " case PARSE_PARTIAL_FROM: {\n"
+ " return new $classname$("
+ " (com.google.protobuf.CodedInputStream) args[0],\n"
+ " (com.google.protobuf.ExtensionRegistryLite) args[1]);\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"
+ " }\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Indent();
+ printer->Indent();
+
+ printer->Print(
+ "case IS_INITIALIZED: {\n");
+ printer->Indent();
+ GenerateDynamicMethodIsInitialized(printer);
+ printer->Outdent();
+
+ printer->Print(
+ "}\n"
+ "case MAKE_IMMUTABLE: {\n");
+
+ printer->Indent();
+ GenerateDynamicMethodMakeImmutable(printer);
+ printer->Outdent();
+
+ printer->Print(
+ "}\n"
+ "case NEW_BUILDER: {\n");
+
+ printer->Indent();
+ GenerateDynamicMethodNewBuilder(printer);
+ printer->Outdent();
+
+ printer->Print(
+ "}\n"
+ "case MERGE_FROM: {\n");
+
+ printer->Indent();
+ GenerateDynamicMethodMergeFrom(printer);
+ printer->Outdent();
+
+ printer->Print(
+ "}\n");
+
+ printer->Outdent();
+ printer->Outdent();
+
+ printer->Print(
+ " }\n"
+ " throw new UnsupportedOperationException();\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(class_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
+
+ // Carefully initialize the default instance in such a way that it doesn't
+ // conflict with other initialization.
+ printer->Print(
+ "private static final $classname$ DEFAULT_INSTANCE;\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "static {\n"
+ " DEFAULT_INSTANCE = new $classname$(\n"
+ " com.google.protobuf.Internal\n"
+ " .EMPTY_CODED_INPUT_STREAM,\n"
+ " com.google.protobuf.ExtensionRegistryLite\n"
+ " .getEmptyRegistry());\n"
+ "}\n"
+ "\n",
+ "classname", descriptor_->name());
+ printer->Print(
+ "public static $classname$ getDefaultInstance() {\n"
+ " return DEFAULT_INSTANCE;\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ GenerateParser(printer);
+
+ // LITE_RUNTIME uses this to implement the *ForType methods at the
+ // GeneratedMessageLite level.
+ printer->Print(
+ "static {\n"
+ " com.google.protobuf.GeneratedMessageLite.onLoad(\n"
+ " $classname$.class, new com.google.protobuf.GeneratedMessageLite\n"
+ " .PrototypeHolder<$classname$, Builder>(\n"
+ " DEFAULT_INSTANCE, PARSER));"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ // Extensions must be declared after the DEFAULT_INSTANCE is initialized
+ // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
+ // the outer class's FileDescriptor.
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ ImmutableExtensionGenerator(descriptor_->extension(i), context_)
+ .Generate(printer);
+ }
+
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::
+GenerateMessageSerializationMethods(io::Printer* printer) {
+ google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
+ SortFieldsByNumber(descriptor_));
+
+ vector<const Descriptor::ExtensionRange*> sorted_extensions;
+ for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+ sorted_extensions.push_back(descriptor_->extension_range(i));
+ }
+ std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+ ExtensionRangeOrdering());
+
+ printer->Print(
+ "public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
+ " throws java.io.IOException {\n");
+ printer->Indent();
+ if (HasPackedFields(descriptor_)) {
+ // writeTo(CodedOutputStream output) might be invoked without
+ // getSerializedSize() ever being called, but we need the memoized
+ // sizes in case this message has packed fields. Rather than emit checks for
+ // each packed field, just call getSerializedSize() up front.
+ // In most cases, getSerializedSize() will have already been called anyway
+ // by one of the wrapper writeTo() methods, making this call cheap.
+ printer->Print(
+ "getSerializedSize();\n");
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ if (descriptor_->options().message_set_wire_format()) {
+ printer->Print(
+ "com.google.protobuf.GeneratedMessageLite\n"
+ " .ExtendableMessage<$classname$, $classname$.Builder>\n"
+ " .ExtensionWriter extensionWriter =\n"
+ " newMessageSetExtensionWriter();\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ } else {
+ printer->Print(
+ "com.google.protobuf.GeneratedMessageLite\n"
+ " .ExtendableMessage<$classname$, $classname$.Builder>\n"
+ " .ExtensionWriter extensionWriter =\n"
+ " newExtensionWriter();\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ }
+ }
+
+ // Merge the fields and the extension ranges, both sorted by field number.
+ for (int i = 0, j = 0;
+ i < descriptor_->field_count() || j < sorted_extensions.size();
+ ) {
+ if (i == descriptor_->field_count()) {
+ GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+ } else if (j == sorted_extensions.size()) {
+ GenerateSerializeOneField(printer, sorted_fields[i++]);
+ } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) {
+ GenerateSerializeOneField(printer, sorted_fields[i++]);
+ } else {
+ GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+ }
+ }
+
+ if (PreserveUnknownFields(descriptor_)) {
+ printer->Print(
+ "unknownFields.writeTo(output);\n");
+ }
+
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n"
+ "public int getSerializedSize() {\n"
+ " int size = memoizedSerializedSize;\n"
+ " if (size != -1) return size;\n"
+ "\n"
+ " size = 0;\n");
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ if (descriptor_->options().message_set_wire_format()) {
+ printer->Print(
+ "size += extensionsSerializedSizeAsMessageSet();\n");
+ } else {
+ printer->Print(
+ "size += extensionsSerializedSize();\n");
+ }
+ }
+
+ if (PreserveUnknownFields(descriptor_)) {
+ printer->Print(
+ "size += unknownFields.getSerializedSize();\n");
+ }
+
+ printer->Outdent();
+ printer->Print(
+ " memoizedSerializedSize = size;\n"
+ " return size;\n"
+ "}\n"
+ "\n");
+
+ printer->Print(
+ "private static final long serialVersionUID = 0L;\n");
+}
+
+void ImmutableMessageLiteGenerator::
+GenerateParseFromMethods(io::Printer* printer) {
+ // Note: These are separate from GenerateMessageSerializationMethods()
+ // because they need to be generated even for messages that are optimized
+ // for code size.
+ printer->Print(
+ "public static $classname$ parseFrom(\n"
+ " com.google.protobuf.ByteString data)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return PARSER.parseFrom(data);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " com.google.protobuf.ByteString data,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return PARSER.parseFrom(data, extensionRegistry);\n"
+ "}\n"
+ "public static $classname$ parseFrom(byte[] data)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return PARSER.parseFrom(data);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " byte[] data,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return PARSER.parseFrom(data, extensionRegistry);\n"
+ "}\n"
+ "public static $classname$ parseFrom(java.io.InputStream input)\n"
+ " throws java.io.IOException {\n"
+ " return PARSER.parseFrom(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"
+ "}\n"
+ "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
+ " throws java.io.IOException {\n"
+ " return PARSER.parseDelimitedFrom(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"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " com.google.protobuf.CodedInputStream input)\n"
+ " throws java.io.IOException {\n"
+ " return PARSER.parseFrom(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"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+}
+
+void ImmutableMessageLiteGenerator::GenerateSerializeOneField(
+ io::Printer* printer, const FieldDescriptor* field) {
+ field_generators_.get(field).GenerateSerializationCode(printer);
+}
+
+void ImmutableMessageLiteGenerator::GenerateSerializeOneExtensionRange(
+ io::Printer* printer, const Descriptor::ExtensionRange* range) {
+ printer->Print(
+ "extensionWriter.writeUntil($end$, output);\n",
+ "end", SimpleItoa(range->end));
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateBuilder(io::Printer* printer) {
+ printer->Print(
+ "public static Builder newBuilder() {\n"
+ " return DEFAULT_INSTANCE.toBuilder();\n"
+ "}\n"
+ "public static Builder newBuilder($classname$ prototype) {\n"
+ " return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ MessageBuilderLiteGenerator builderGenerator(descriptor_, context_);
+ builderGenerator.Generate(printer);
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized(
+ io::Printer* printer) {
+ // Returns null for false, DEFAULT_INSTANCE for true.
+ if (!HasRequiredFields(descriptor_)) {
+ printer->Print("return DEFAULT_INSTANCE;\n");
+ return;
+ }
+
+ // Don't directly compare to -1 to avoid an Android x86 JIT bug.
+ printer->Print(
+ "byte isInitialized = memoizedIsInitialized;\n"
+ "if (isInitialized == 1) return DEFAULT_INSTANCE;\n"
+ "if (isInitialized == 0) return null;\n"
+ "\n"
+ "boolean shouldMemoize = ((Boolean) args[0]).booleanValue();\n");
+
+ // Check that all required fields in this message are set.
+ // TODO(kenton): We can optimize this when we switch to putting all the
+ // "has" fields into a single bitfield.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+
+ if (field->is_required()) {
+ printer->Print(
+ "if (!has$name$()) {\n"
+ " if (shouldMemoize) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " }\n"
+ " return null;\n"
+ "}\n",
+ "name", info->capitalized_name);
+ }
+ }
+
+ // Now check that all embedded messages are initialized.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+ HasRequiredFields(field->message_type())) {
+ switch (field->label()) {
+ case FieldDescriptor::LABEL_REQUIRED:
+ printer->Print(
+ "if (!get$name$().isInitialized()) {\n"
+ " if (shouldMemoize) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " }\n"
+ " return null;\n"
+ "}\n",
+ "type", name_resolver_->GetImmutableClassName(
+ field->message_type()),
+ "name", info->capitalized_name);
+ break;
+ case FieldDescriptor::LABEL_OPTIONAL:
+ if (!SupportFieldPresence(descriptor_->file()) &&
+ field->containing_oneof() != NULL) {
+ const OneofDescriptor* oneof = field->containing_oneof();
+ const OneofGeneratorInfo* oneof_info =
+ context_->GetOneofGeneratorInfo(oneof);
+ printer->Print(
+ "if ($oneof_name$Case_ == $field_number$) {\n",
+ "oneof_name", oneof_info->name,
+ "field_number", SimpleItoa(field->number()));
+ } else {
+ printer->Print(
+ "if (has$name$()) {\n",
+ "name", info->capitalized_name);
+ }
+ printer->Print(
+ " if (!get$name$().isInitialized()) {\n"
+ " if (shouldMemoize) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " }\n"
+ " return null;\n"
+ " }\n"
+ "}\n",
+ "name", info->capitalized_name);
+ break;
+ case FieldDescriptor::LABEL_REPEATED:
+ if (IsMapEntry(field->message_type())) {
+ printer->Print(
+ "for ($type$ item : get$name$().values()) {\n"
+ " if (!item.isInitialized()) {\n"
+ " if (shouldMemoize) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " }\n"
+ " return null;\n"
+ " }\n"
+ "}\n",
+ "type", MapValueImmutableClassdName(field->message_type(),
+ name_resolver_),
+ "name", info->capitalized_name);
+ } else {
+ printer->Print(
+ "for (int i = 0; i < get$name$Count(); i++) {\n"
+ " if (!get$name$(i).isInitialized()) {\n"
+ " if (shouldMemoize) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " }\n"
+ " return null;\n"
+ " }\n"
+ "}\n",
+ "type", name_resolver_->GetImmutableClassName(
+ field->message_type()),
+ "name", info->capitalized_name);
+ }
+ break;
+ }
+ }
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "if (!extensionsAreInitialized()) {\n"
+ " if (shouldMemoize) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " }\n"
+ " return null;\n"
+ "}\n");
+ }
+
+ printer->Print(
+ "if (shouldMemoize) memoizedIsInitialized = 1;\n");
+
+ printer->Print(
+ "return DEFAULT_INSTANCE;\n"
+ "\n");
+}
+
+// ===================================================================
+
+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;");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuilder(
+ io::Printer* printer) {
+ printer->Print(
+ "return new Builder();");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom(
+ 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.
+ "Object arg = args[0];\n"
+ "if (arg == $classname$.getDefaultInstance()) return this;\n"
+ "$classname$ other = ($classname$) arg;\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);
+ }
+ }
+
+ // Merge oneof fields.
+ for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
+ printer->Print(
+ "switch (other.get$oneof_capitalized_name$Case()) {\n",
+ "oneof_capitalized_name",
+ context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->capitalized_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(
+ "case $field_name$: {\n",
+ "field_name",
+ ToUpper(field->name()));
+ printer->Indent();
+ field_generators_.get(field).GenerateMergingCode(printer);
+ printer->Print(
+ "break;\n");
+ printer->Outdent();
+ printer->Print(
+ "}\n");
+ }
+ printer->Print(
+ "case $cap_oneof_name$_NOT_SET: {\n"
+ " break;\n"
+ "}\n",
+ "cap_oneof_name",
+ ToUpper(context_->GetOneofGeneratorInfo(
+ 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");
+ 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.
+ printer->Print(
+ "result = result && unknownFields.equals(other.unknownFields);\n");
+ }
+ 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_));
+
+ 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(
+ "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");
+ }
+ }
+
+ printer->Print(
+ "hash = (29 * hash) + unknownFields.hashCode();\n");
+ printer->Print(
+ "memoizedHashCode = hash;\n"
+ "return hash;\n");
+ printer->Outdent();
+ printer->Print(
+ "}\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);
+ }
+}
+
+// ===================================================================
+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));
+ }
+
+ if (PreserveUnknownFields(descriptor_)) {
+ printer->Print(
+ "com.google.protobuf.UnknownFieldSetLite.Builder unknownFields =\n"
+ " com.google.protobuf.UnknownFieldSetLite.newBuilder();\n");
+ }
+
+ printer->Print(
+ "try {\n");
+ printer->Indent();
+
+ printer->Print(
+ "boolean done = false;\n"
+ "while (!done) {\n");
+ printer->Indent();
+
+ printer->Print(
+ "int tag = input.readTag();\n"
+ "switch (tag) {\n");
+ printer->Indent();
+
+ printer->Print(
+ "case 0:\n" // zero signals EOF / limit reached
+ " done = true;\n"
+ " break;\n");
+
+ if (PreserveUnknownFields(descriptor_)) {
+ if (descriptor_->extension_range_count() > 0) {
+ // Lite runtime directly invokes parseUnknownField to reduce method
+ // counts.
+ printer->Print(
+ "default: {\n"
+ " if (!parseUnknownField(extensions, getDefaultInstanceForType(),\n"
+ " input, unknownFields,\n"
+ " extensionRegistry, tag)) {\n"
+ " done = true;\n" // it's an endgroup tag
+ " }\n"
+ " break;\n"
+ "}\n");
+ } else {
+ printer->Print(
+ "default: {\n"
+ " if (!parseUnknownField(input, unknownFields,\n"
+ " extensionRegistry, tag)) {\n"
+ " done = true;\n" // it's an endgroup tag
+ " }\n"
+ " break;\n"
+ "}\n");
+ }
+ } else {
+ printer->Print(
+ "default: {\n"
+ " if (!input.skipField(tag)) {\n"
+ " done = true;\n" // it's an endgroup tag
+ " }\n"
+ " break;\n"
+ "}\n");
+ }
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = sorted_fields[i];
+ uint32 tag = WireFormatLite::MakeTag(field->number(),
+ WireFormat::WireTypeForFieldType(field->type()));
+
+ printer->Print(
+ "case $tag$: {\n",
+ "tag", SimpleItoa(tag));
+ printer->Indent();
+
+ field_generators_.get(field).GenerateParsingCode(printer);
+
+ printer->Outdent();
+ printer->Print(
+ " break;\n"
+ "}\n");
+
+ if (field->is_packable()) {
+ // To make packed = true wire compatible, we generate parsing code from a
+ // packed version of this field regardless of field->options().packed().
+ uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+ printer->Print(
+ "case $tag$: {\n",
+ "tag", SimpleItoa(packed_tag));
+ printer->Indent();
+
+ field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
+
+ printer->Outdent();
+ printer->Print(
+ " break;\n"
+ "}\n");
+ }
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n" // switch (tag)
+ "}\n"); // while (!done)
+
+ printer->Outdent();
+ printer->Print(
+ "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
+ " throw new RuntimeException(e.setUnfinishedMessage(this));\n"
+ "} catch (java.io.IOException e) {\n"
+ " throw new RuntimeException(\n"
+ " new com.google.protobuf.InvalidProtocolBufferException(\n"
+ " e.getMessage()).setUnfinishedMessage(this));\n"
+ "} finally {\n");
+ printer->Indent();
+
+ // Make repeated field list immutable.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = sorted_fields[i];
+ field_generators_.get(field).GenerateParsingDoneCode(printer);
+ }
+
+ if (PreserveUnknownFields(descriptor_)) {
+ // Make unknown fields immutable.
+ printer->Print("this.unknownFields = unknownFields.build();\n");
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ // Make extensions immutable.
+ printer->Print(
+ "makeExtensionsImmutable(extensions);\n");
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n" // finally
+ "}\n");
+}
+
+// ===================================================================
+void ImmutableMessageLiteGenerator::GenerateParser(io::Printer* printer) {
+ printer->Print(
+ "public static final com.google.protobuf.Parser<$classname$> PARSER =\n"
+ " new DefaultInstanceBasedParser(DEFAULT_INSTANCE);\n"
+ "\n",
+ "classname", descriptor_->name());
+}
+
+// ===================================================================
+void ImmutableMessageLiteGenerator::GenerateInitializers(io::Printer* printer) {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!descriptor_->field(i)->containing_oneof()) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateInitializationCode(printer);
+ }
+ }
+}
+
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_message_lite.h b/src/google/protobuf/compiler/java/java_message_lite.h
new file mode 100644
index 00000000..2bd3cdd4
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_lite.h
@@ -0,0 +1,91 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__
+
+#include <string>
+#include <map>
+#include <google/protobuf/compiler/java/java_field.h>
+#include <google/protobuf/compiler/java/java_message.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMessageLiteGenerator : public MessageGenerator {
+ public:
+ explicit ImmutableMessageLiteGenerator(const Descriptor* descriptor,
+ Context* context);
+ virtual ~ImmutableMessageLiteGenerator();
+
+ 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 int GenerateStaticVariableInitializers(io::Printer* printer);
+
+ private:
+
+ void GenerateMessageSerializationMethods(io::Printer* printer);
+ void GenerateParseFromMethods(io::Printer* printer);
+ void GenerateSerializeOneField(io::Printer* printer,
+ const FieldDescriptor* field);
+ void GenerateSerializeOneExtensionRange(
+ io::Printer* printer, const Descriptor::ExtensionRange* range);
+
+ void GenerateBuilder(io::Printer* printer);
+ void GenerateDynamicMethodIsInitialized(io::Printer* printer);
+ void GenerateDynamicMethodMakeImmutable(io::Printer* printer);
+ void GenerateDynamicMethodMergeFrom(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);
+
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+ FieldGeneratorMap<ImmutableFieldLiteGenerator> field_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index e331d7a4..7bebe12a 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -74,7 +74,12 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
"" : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
(*variables)["capitalized_type"] =
GetCapitalizedType(descriptor, /* immutable = */ true);
- (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+ if (descriptor->is_packed()) {
+ (*variables)["tag"] = SimpleItoa(WireFormatLite::MakeTag(
+ descriptor->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
+ } else {
+ (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+ }
(*variables)["tag_size"] = SimpleItoa(
WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
if (IsReferenceType(GetJavaType(descriptor))) {
@@ -599,7 +604,7 @@ GenerateMembers(io::Printer* printer) const {
" return $name$_.get(index);\n"
"}\n");
- if (descriptor_->options().packed() &&
+ if (descriptor_->is_packed() &&
HasGeneratedMethods(descriptor_->containing_type())) {
printer->Print(variables_,
"private int $name$MemoizedSerializedSize = -1;\n");
@@ -771,7 +776,10 @@ GenerateParsingDoneCode(io::Printer* printer) const {
void RepeatedImmutablePrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
+ // We invoke getSerializedSize in writeTo for messages that have packed
+ // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
+ // That makes it safe to rely on the memoized size here.
printer->Print(variables_,
"if (get$capitalized_name$List().size() > 0) {\n"
" output.writeRawVarint32($tag$);\n"
@@ -809,7 +817,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(
"size += dataSize;\n");
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
"if (!get$capitalized_name$List().isEmpty()) {\n"
" size += $tag_size$;\n"
@@ -822,7 +830,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
}
// cache the data size for packed fields.
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
"$name$MemoizedSerializedSize = dataSize;\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
new file mode 100644
index 00000000..217ff9b6
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
@@ -0,0 +1,892 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/common.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/compiler/java/java_primitive_field_lite.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ map<string, string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+
+ (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
+ (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
+ (*variables)["field_type"] = (*variables)["type"];
+ (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ?
+ "" : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
+ (*variables)["capitalized_type"] =
+ GetCapitalizedType(descriptor, /* immutable = */ true);
+ (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+ (*variables)["tag_size"] = SimpleItoa(
+ WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+
+ string capitalized_type = UnderscoresToCamelCase(PrimitiveTypeName(
+ GetJavaType(descriptor)), true /* cap_next_letter */);
+ switch (GetJavaType(descriptor)) {
+ case JAVATYPE_INT:
+ case JAVATYPE_LONG:
+ case JAVATYPE_FLOAT:
+ case JAVATYPE_DOUBLE:
+ case JAVATYPE_BOOLEAN:
+ (*variables)["field_list_type"] =
+ "com.google.protobuf.Internal." + capitalized_type + "List";
+ (*variables)["new_list"] = "new" + capitalized_type + "List";
+ (*variables)["empty_list"] = "empty" + capitalized_type + "List()";
+ (*variables)["make_name_unmodifiable"] =
+ (*variables)["name"] + "_.makeImmutable()";
+ (*variables)["repeated_index_get"] =
+ (*variables)["name"] + "_.get" + capitalized_type + "(index)";
+ (*variables)["repeated_add"] =
+ (*variables)["name"] + "_.add" + capitalized_type;
+ (*variables)["repeated_set"] =
+ (*variables)["name"] + "_.set" + capitalized_type;
+ break;
+ default:
+ (*variables)["field_list_type"] =
+ "com.google.protobuf.Internal.ProtobufList<" +
+ (*variables)["boxed_type"] + ">";
+ (*variables)["new_list"] = "newProtobufList";
+ (*variables)["empty_list"] = "emptyProtobufList()";
+ (*variables)["make_name_unmodifiable"] =
+ (*variables)["name"] + "_.makeImmutable()";
+ (*variables)["repeated_index_get"] =
+ (*variables)["name"] + "_.get(index)";
+ (*variables)["repeated_add"] = (*variables)["name"] + "_.add";
+ (*variables)["repeated_set"] = (*variables)["name"] + "_.set";
+ }
+
+ if (IsReferenceType(GetJavaType(descriptor))) {
+ (*variables)["null_check"] =
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n";
+ } else {
+ (*variables)["null_check"] = "";
+ }
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] = descriptor->options().deprecated()
+ ? "@java.lang.Deprecated " : "";
+ int fixed_size = FixedSize(GetType(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.
+ (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+ // Note that these have a trailing ";".
+ (*variables)["set_has_field_bit_message"] =
+ GenerateSetBit(messageBitIndex) + ";";
+ (*variables)["clear_has_field_bit_message"] =
+ GenerateClearBit(messageBitIndex) + ";";
+
+ (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+ } else {
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["clear_has_field_bit_message"] = "";
+
+ if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
+ (*variables)["is_field_present_message"] =
+ "!" + (*variables)["name"] + "_.isEmpty()";
+ } else {
+ (*variables)["is_field_present_message"] =
+ (*variables)["name"] + "_ != " + (*variables)["default"];
+ }
+ }
+
+ // For repeated builders, the underlying list tracks mutability state.
+ (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
+
+ (*variables)["get_has_field_bit_from_local"] =
+ GenerateGetBitFromLocal(builderBitIndex);
+ (*variables)["set_has_field_bit_to_local"] =
+ GenerateSetBitToLocal(messageBitIndex);
+}
+
+} // namespace
+
+// ===================================================================
+
+ImmutablePrimitiveFieldLiteGenerator::
+ImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+ImmutablePrimitiveFieldLiteGenerator::~ImmutablePrimitiveFieldLiteGenerator() {}
+
+int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 1;
+}
+
+int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$boolean has$capitalized_name$();\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private $field_type$ $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+ }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return $name$_;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ "$null_check$"
+ " $set_has_field_bit_message$\n"
+ " $name$_ = value;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $clear_has_field_bit_message$\n");
+ JavaType type = GetJavaType(descriptor_);
+ if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
+ // The default value is not a simple literal so we want to avoid executing
+ // it multiple times. Instead, get the default out of the default instance.
+ printer->Print(variables_,
+ " $name$_ = getDefaultInstance().get$capitalized_name$();\n");
+ } else {
+ printer->Print(variables_,
+ " $name$_ = $default$;\n");
+ }
+ printer->Print(variables_,
+ "}\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // noop for primitives
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+ // noop for primitives
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateMergingCode(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");
+ } else {
+ printer->Print(variables_,
+ "if (other.get$capitalized_name$() != $default$) {\n"
+ " set$capitalized_name$(other.get$capitalized_name$());\n"
+ "}\n");
+ }
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+ // noop for primitives
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ // noop for scalars
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$set_has_field_bit_message$\n"
+ "$name$_ = input.read$capitalized_type$();\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ // noop for primitives.
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " output.write$capitalized_type$($number$, $name$_);\n"
+ "}\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .compute$capitalized_type$Size($number$, $name$_);\n"
+ "}\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ switch (GetJavaType(descriptor_)) {
+ case JAVATYPE_INT:
+ case JAVATYPE_LONG:
+ case JAVATYPE_BOOLEAN:
+ printer->Print(variables_,
+ "result = result && (get$capitalized_name$()\n"
+ " == other.get$capitalized_name$());\n");
+ break;
+
+ case JAVATYPE_FLOAT:
+ printer->Print(variables_,
+ "result = result && (\n"
+ " java.lang.Float.floatToIntBits(get$capitalized_name$())\n"
+ " == java.lang.Float.floatToIntBits(\n"
+ " other.get$capitalized_name$()));\n");
+ break;
+
+ case JAVATYPE_DOUBLE:
+ printer->Print(variables_,
+ "result = result && (\n"
+ " java.lang.Double.doubleToLongBits(get$capitalized_name$())\n"
+ " == java.lang.Double.doubleToLongBits(\n"
+ " other.get$capitalized_name$()));\n");
+ break;
+
+ case JAVATYPE_STRING:
+ case JAVATYPE_BYTES:
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$()\n"
+ " .equals(other.get$capitalized_name$());\n");
+ break;
+
+ case JAVATYPE_ENUM:
+ case JAVATYPE_MESSAGE:
+ default:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ break;
+ }
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n");
+ switch (GetJavaType(descriptor_)) {
+ case JAVATYPE_INT:
+ printer->Print(variables_,
+ "hash = (53 * hash) + get$capitalized_name$();\n");
+ break;
+
+ case JAVATYPE_LONG:
+ printer->Print(variables_,
+ "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
+ " get$capitalized_name$());\n");
+ break;
+
+ case JAVATYPE_BOOLEAN:
+ printer->Print(variables_,
+ "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n"
+ " get$capitalized_name$());\n");
+ break;
+
+ case JAVATYPE_FLOAT:
+ printer->Print(variables_,
+ "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n"
+ " get$capitalized_name$());\n");
+ break;
+
+ case JAVATYPE_DOUBLE:
+ printer->Print(variables_,
+ "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
+ " java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n");
+ break;
+
+ case JAVATYPE_STRING:
+ case JAVATYPE_BYTES:
+ printer->Print(variables_,
+ "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+ break;
+
+ case JAVATYPE_ENUM:
+ case JAVATYPE_MESSAGE:
+ default:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ break;
+ }
+}
+
+string ImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const {
+ return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
+}
+
+// ===================================================================
+
+ImmutablePrimitiveOneofFieldLiteGenerator::
+ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : ImmutablePrimitiveFieldLiteGenerator(
+ descriptor, messageBitIndex, builderBitIndex, context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutablePrimitiveOneofFieldLiteGenerator::
+~ImmutablePrimitiveOneofFieldLiteGenerator() {}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($boxed_type$) $oneof_name$_;\n"
+ " }\n"
+ " return $default$;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ "$null_check$"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ "}\n");
+}
+
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+ // noop for primitives
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "set$capitalized_name$(other.get$capitalized_name$());\n");
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = input.read$capitalized_type$();\n");
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " output.write$capitalized_type$(\n"
+ " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"
+ "}\n");
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .compute$capitalized_type$Size(\n"
+ " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"
+ "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutablePrimitiveFieldLiteGenerator::
+RepeatedImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+RepeatedImmutablePrimitiveFieldLiteGenerator::
+~RepeatedImmutablePrimitiveFieldLiteGenerator() {}
+
+int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$(int index);\n");
+}
+
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private $field_list_type$ $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$boxed_type$>\n"
+ " get$capitalized_name$List() {\n"
+ " return $name$_;\n" // note: unmodifiable list
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+ " return $repeated_index_get$;\n"
+ "}\n");
+
+ if (descriptor_->options().packed() &&
+ HasGeneratedMethods(descriptor_->containing_type())) {
+ printer->Print(variables_,
+ "private int $name$MemoizedSerializedSize = -1;\n");
+ }
+
+ printer->Print(variables_,
+ "private void ensure$capitalized_name$IsMutable() {\n"
+ " if (!$is_mutable$) {\n"
+ " $name$_ = $new_list$($name$_);\n"
+ " }\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ "$null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $repeated_set$(index, value);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$($type$ value) {\n"
+ "$null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $repeated_add$(value);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $boxed_type$> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " com.google.protobuf.AbstractMessageLite.addAll(\n"
+ " values, $name$_);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $name$_ = $empty_list$;\n"
+ "}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$boxed_type$>\n"
+ " get$capitalized_name$List() {\n"
+ " return java.util.Collections.unmodifiableList(\n"
+ " instance.get$capitalized_name$List());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return instance.get$capitalized_name$Count();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+ " return instance.get$capitalized_name$(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $boxed_type$> values) {\n"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$(values);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // noop for primitives
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $empty_list$;\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+ // noop for primitives
+}
+
+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");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+ // noop for primitives
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_.makeImmutable();\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!$is_mutable$) {\n"
+ " $name$_ = $new_list$();\n"
+ "}\n"
+ "$repeated_add$(input.read$capitalized_type$());\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int limit = input.pushLimit(length);\n"
+ "if (!$is_mutable$ && input.getBytesUntilLimit() > 0) {\n"
+ " $name$_ = $new_list$();\n"
+ "}\n"
+ "while (input.getBytesUntilLimit() > 0) {\n"
+ " $repeated_add$(input.read$capitalized_type$());\n"
+ "}\n"
+ "input.popLimit(limit);\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_mutable$) {\n"
+ " $make_name_unmodifiable$;\n"
+ "}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ if (descriptor_->options().packed()) {
+ // We invoke getSerializedSize in writeTo for messages that have packed
+ // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
+ // That makes it safe to rely on the memoized size here.
+ printer->Print(variables_,
+ "if (get$capitalized_name$List().size() > 0) {\n"
+ " output.writeRawVarint32($tag$);\n"
+ " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+ "}\n"
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.write$capitalized_type$NoTag($name$_.get(i));\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.write$capitalized_type$($number$, $name$_.get(i));\n"
+ "}\n");
+ }
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "{\n"
+ " int dataSize = 0;\n");
+ printer->Indent();
+
+ if (FixedSize(GetType(descriptor_)) == -1) {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " dataSize += com.google.protobuf.CodedOutputStream\n"
+ " .compute$capitalized_type$SizeNoTag($name$_.get(i));\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
+ }
+
+ printer->Print(
+ "size += dataSize;\n");
+
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (!get$capitalized_name$List().isEmpty()) {\n"
+ " size += $tag_size$;\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeInt32SizeNoTag(dataSize);\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "size += $tag_size$ * get$capitalized_name$List().size();\n");
+ }
+
+ // cache the data size for packed fields.
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "$name$MemoizedSerializedSize = dataSize;\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$List()\n"
+ " .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (get$capitalized_name$Count() > 0) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+ "}\n");
+}
+
+string RepeatedImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const {
+ return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.h b/src/google/protobuf/compiler/java/java_primitive_field_lite.h
new file mode 100644
index 00000000..ad603c2a
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.h
@@ -0,0 +1,163 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ class ClassNameResolver; // name_resolver.h
+ }
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutablePrimitiveFieldLiteGenerator
+ : public ImmutableFieldLiteGenerator {
+ public:
+ explicit ImmutablePrimitiveFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutablePrimitiveFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ int GetNumBitsForMessage() const;
+ int GetNumBitsForBuilder() const;
+ void GenerateInterfaceMembers(io::Printer* printer) const;
+ void GenerateMembers(io::Printer* printer) const;
+ 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 GenerateBuildingCode(io::Printer* printer) const;
+ void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldLiteGenerator);
+};
+
+class ImmutablePrimitiveOneofFieldLiteGenerator
+ : public ImmutablePrimitiveFieldLiteGenerator {
+ public:
+ ImmutablePrimitiveOneofFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~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 GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutablePrimitiveFieldLiteGenerator
+ : public ImmutableFieldLiteGenerator {
+ public:
+ explicit RepeatedImmutablePrimitiveFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ virtual ~RepeatedImmutablePrimitiveFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ int GetNumBitsForMessage() const;
+ int GetNumBitsForBuilder() const;
+ void GenerateInterfaceMembers(io::Printer* printer) const;
+ void GenerateMembers(io::Printer* printer) const;
+ 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 GenerateBuildingCode(io::Printer* printer) const;
+ void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
index 2e61ea8a..70177367 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
@@ -171,7 +171,7 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) {
string classname = FileJavaPackage(file_->dependency(i)) + "." +
name_resolver_->GetDescriptorClassName(
file_->dependency(i));
- dependencies.push_back(make_pair(filename, classname));
+ dependencies.push_back(std::make_pair(filename, classname));
}
}
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
index 1c9302af..68e863cc 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -208,7 +208,7 @@ GenerateInterfaceMembers(io::Printer* printer) const {
void ImmutableStringFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private java.lang.Object $name$_;\n");
+ "private volatile java.lang.Object $name$_;\n");
PrintExtraFieldInfo(variables_, printer);
if (SupportFieldPresence(descriptor_->file())) {
@@ -667,7 +667,7 @@ GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"String s = input.readStringRequireUtf8();\n"
"$set_oneof_case_message$;\n"
- "$oneof_name$_ = s;\n}\n");
+ "$oneof_name$_ = s;\n");
} else if (!HasDescriptorMethods(descriptor_->file())) {
// Lite runtime should attempt to reduce allocations by attempting to
// construct the string directly from the input stream buffer. This avoids
diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.cc b/src/google/protobuf/compiler/java/java_string_field_lite.cc
new file mode 100644
index 00000000..51bb245c
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc
@@ -0,0 +1,1013 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Author: jonp@google.com (Jon Perlow)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/common.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/compiler/java/java_string_field_lite.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ map<string, string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+
+ (*variables)["empty_list"] = "emptyLazyStringArrayList()";
+
+ (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["default_init"] =
+ "= " + ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["capitalized_type"] = "String";
+ (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+ (*variables)["tag_size"] = SimpleItoa(
+ WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+ (*variables)["null_check"] =
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n";
+
+ // 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();" : "";
+
+ if (SupportFieldPresence(descriptor->file())) {
+ // For singular messages and builders, one bit is used for the hasField bit.
+ (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+ // Note that these have a trailing ";".
+ (*variables)["set_has_field_bit_message"] =
+ GenerateSetBit(messageBitIndex) + ";";
+ (*variables)["clear_has_field_bit_message"] =
+ GenerateClearBit(messageBitIndex) + ";";
+
+ (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+ } else {
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["clear_has_field_bit_message"] = "";
+
+ (*variables)["is_field_present_message"] =
+ "!get" + (*variables)["capitalized_name"] + "Bytes().isEmpty()";
+ }
+
+ // For repeated builders, the underlying list tracks mutability state.
+ (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
+
+ (*variables)["get_has_field_bit_from_local"] =
+ GenerateGetBitFromLocal(builderBitIndex);
+ (*variables)["set_has_field_bit_to_local"] =
+ GenerateSetBitToLocal(messageBitIndex);
+}
+
+bool CheckUtf8(const FieldDescriptor* descriptor) {
+ return descriptor->file()->options().java_string_check_utf8();
+}
+
+} // namespace
+
+// ===================================================================
+
+ImmutableStringFieldLiteGenerator::
+ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {}
+
+int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 1;
+}
+
+int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+// A note about how strings are handled. This code used to just store a String
+// in the Message. This had two issues:
+//
+// 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded
+// strings, but rather fields that were raw bytes incorrectly marked
+// as strings in the proto file. This is common because in the proto1
+// syntax, string was the way to indicate bytes and C++ engineers can
+// easily make this mistake without affecting the C++ API. By converting to
+// strings immediately, some java code might corrupt these byte arrays as
+// it passes through a java server even if the field was never accessed by
+// application code.
+//
+// 2. There's a performance hit to converting between bytes and strings and
+// it many cases, the field is never even read by the application code. This
+// avoids unnecessary conversions in the common use cases.
+//
+// So now, the field for String is maintained as an Object reference which can
+// either store a String or a ByteString. The code uses an instanceof check
+// to see which one it has and converts to the other one if needed. It remembers
+// the last value requested (in a thread safe manner) as this is most likely
+// the one needed next. The thread safety is such that if two threads both
+// convert the field because the changes made by each thread were not visible to
+// the other, they may cause a conversion to happen more times than would
+// otherwise be necessary. This was deemed better than adding synchronization
+// overhead. It will not cause any corruption issues or affect the behavior of
+// the API. The instanceof check is also highly optimized in the JVM and we
+// decided it was better to reduce the memory overhead by not having two
+// separate fields but rather use dynamic type checking.
+//
+// For single fields, the logic for this is done inside the generated code. For
+// repeated fields, the logic is done in LazyStringArrayList and
+// UnmodifiableLazyStringList.
+void ImmutableStringFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$boolean has$capitalized_name$();\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.lang.String get$capitalized_name$();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes();\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private java.lang.Object $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+ }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+ " java.lang.Object ref = $name$_;\n"
+ " if (ref instanceof java.lang.String) {\n"
+ " return (java.lang.String) ref;\n"
+ " } else {\n"
+ " com.google.protobuf.ByteString bs = \n"
+ " (com.google.protobuf.ByteString) ref;\n"
+ " java.lang.String s = bs.toStringUtf8();\n");
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ " $name$_ = s;\n");
+ } else {
+ printer->Print(variables_,
+ " if (bs.isValidUtf8()) {\n"
+ " $name$_ = s;\n"
+ " }\n");
+ }
+ printer->Print(variables_,
+ " return s;\n"
+ " }\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes() {\n"
+ " java.lang.Object ref = $name$_;\n"
+ " if (ref instanceof java.lang.String) {\n"
+ " com.google.protobuf.ByteString b = \n"
+ " com.google.protobuf.ByteString.copyFromUtf8(\n"
+ " (java.lang.String) ref);\n"
+ " $name$_ = b;\n"
+ " return b;\n"
+ " } else {\n"
+ " return (com.google.protobuf.ByteString) ref;\n"
+ " }\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " java.lang.String value) {\n"
+ "$null_check$"
+ " $set_has_field_bit_message$\n"
+ " $name$_ = value;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $clear_has_field_bit_message$\n"
+ // The default value is not a simple literal so we want to avoid executing
+ // it multiple times. Instead, get the default out of the default instance.
+ " $name$_ = getDefaultInstance().get$capitalized_name$();\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$Bytes(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ "$null_check$");
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ " checkByteStringIsUtf8(value);\n");
+ }
+ printer->Print(variables_,
+ " $set_has_field_bit_message$\n"
+ " $name$_ = value;\n"
+ "}\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes() {\n"
+ " return instance.get$capitalized_name$Bytes();\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " java.lang.String value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$Bytes(value);\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // noop for strings
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateMergingCode(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");
+ } else {
+ printer->Print(variables_,
+ "if (!other.get$capitalized_name$().isEmpty()) {\n"
+ " $name$_ = other.$name$_;\n"
+ " $on_changed$\n"
+ "}\n");
+ }
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ // noop for scalars
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ "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_,
+ "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"
+ "$set_has_field_bit_message$\n"
+ "$name$_ = bs;\n");
+ }
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ // noop for strings
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " output.writeBytes($number$, get$capitalized_name$Bytes());\n"
+ "}\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
+ "}\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$()\n"
+ " .equals(other.get$capitalized_name$());\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n");
+ printer->Print(variables_,
+ "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+}
+
+string ImmutableStringFieldLiteGenerator::GetBoxedType() const {
+ return "java.lang.String";
+}
+
+// ===================================================================
+
+ImmutableStringOneofFieldLiteGenerator::
+ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : ImmutableStringFieldLiteGenerator(
+ descriptor, messageBitIndex, builderBitIndex, context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableStringOneofFieldLiteGenerator::
+~ImmutableStringOneofFieldLiteGenerator() {}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+ " java.lang.Object ref $default_init$;\n"
+ " if ($has_oneof_case_message$) {\n"
+ " ref = $oneof_name$_;\n"
+ " }\n"
+ " if (ref instanceof java.lang.String) {\n"
+ " return (java.lang.String) ref;\n"
+ " } else {\n"
+ " com.google.protobuf.ByteString bs = \n"
+ " (com.google.protobuf.ByteString) ref;\n"
+ " java.lang.String s = bs.toStringUtf8();\n");
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ " if ($has_oneof_case_message$) {\n"
+ " $oneof_name$_ = s;\n"
+ " }\n");
+ } else {
+ printer->Print(variables_,
+ " if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n"
+ " $oneof_name$_ = s;\n"
+ " }\n");
+ }
+ printer->Print(variables_,
+ " return s;\n"
+ " }\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes() {\n"
+ " java.lang.Object ref $default_init$;\n"
+ " if ($has_oneof_case_message$) {\n"
+ " ref = $oneof_name$_;\n"
+ " }\n"
+ " if (ref instanceof java.lang.String) {\n"
+ " com.google.protobuf.ByteString b = \n"
+ " com.google.protobuf.ByteString.copyFromUtf8(\n"
+ " (java.lang.String) ref);\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $oneof_name$_ = b;\n"
+ " }\n"
+ " return b;\n"
+ " } else {\n"
+ " return (com.google.protobuf.ByteString) ref;\n"
+ " }\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " java.lang.String value) {\n"
+ "$null_check$"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$Bytes(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ "$null_check$");
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ " checkByteStringIsUtf8(value);\n");
+ }
+ printer->Print(variables_,
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ "}\n");
+}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes() {\n"
+ " return instance.get$capitalized_name$Bytes();\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " java.lang.String value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$Bytes(value);\n"
+ " return this;\n"
+ "}\n");
+}
+
+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.
+ printer->Print(variables_,
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = other.$oneof_name$_;\n"
+ "$on_changed$\n");
+}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ "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_,
+ "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"
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = bs;\n");
+ }
+}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " output.writeBytes($number$, get$capitalized_name$Bytes());\n"
+ "}\n");
+}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
+ "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutableStringFieldLiteGenerator::
+RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+RepeatedImmutableStringFieldLiteGenerator::
+~RepeatedImmutableStringFieldLiteGenerator() {}
+
+int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$com.google.protobuf.ProtocolStringList\n"
+ " get$capitalized_name$List();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes(int index);\n");
+}
+
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private com.google.protobuf.LazyStringArrayList $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ProtocolStringList\n"
+ " get$capitalized_name$List() {\n"
+ " return $name$_;\n" // note: unmodifiable list
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes(int index) {\n"
+ " return $name$_.getByteString(index);\n"
+ "}\n");
+
+ if (descriptor_->options().packed() &&
+ HasGeneratedMethods(descriptor_->containing_type())) {
+ printer->Print(variables_,
+ "private int $name$MemoizedSerializedSize = -1;\n");
+ }
+
+ printer->Print(variables_,
+ "private void ensure$capitalized_name$IsMutable() {\n"
+ " if (!$is_mutable$) {\n"
+ " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n"
+ " }\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, java.lang.String value) {\n"
+ "$null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, value);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$(\n"
+ " java.lang.String value) {\n"
+ "$null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void addAll$capitalized_name$(\n"
+ " java.lang.Iterable<java.lang.String> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " com.google.protobuf.AbstractMessageLite.addAll(\n"
+ " values, $name$_);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $name$_ = $empty_list$;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$Bytes(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ "$null_check$");
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ " checkByteStringIsUtf8(value);\n");
+ }
+ printer->Print(variables_,
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value);\n"
+ "}\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ProtocolStringList\n"
+ " get$capitalized_name$List() {\n"
+ " return ((com.google.protobuf.LazyStringList)\n"
+ " instance.get$capitalized_name$List()).getUnmodifiableView();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return instance.get$capitalized_name$Count();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
+ " return instance.get$capitalized_name$(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes(int index) {\n"
+ " return instance.get$capitalized_name$Bytes(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " int index, java.lang.String value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$(\n"
+ " java.lang.String value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder addAll$capitalized_name$(\n"
+ " java.lang.Iterable<java.lang.String> values) {\n"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$(values);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$Bytes(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$Bytes(value);\n"
+ " return this;\n"
+ "}\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // noop for strings
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $empty_list$;\n");
+}
+
+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");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_.makeImmutable();\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ "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_,
+ "String s = input.readString();\n");
+ } else {
+ printer->Print(variables_,
+ "com.google.protobuf.ByteString bs = input.readBytes();\n");
+ }
+ printer->Print(variables_,
+ "if (!$is_mutable$) {\n"
+ " $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
+ "}\n");
+ if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) {
+ printer->Print(variables_,
+ "$name$_.add(s);\n");
+ } else {
+ printer->Print(variables_,
+ "$name$_.add(bs);\n");
+ }
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int limit = input.pushLimit(length);\n"
+ "if (!$is_mutable$ && input.getBytesUntilLimit() > 0) {\n"
+ " $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
+ "}\n"
+ "while (input.getBytesUntilLimit() > 0) {\n");
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ " String s = input.readStringRequireUtf8();\n");
+ } else {
+ printer->Print(variables_,
+ " String s = input.readString();\n");
+ }
+ printer->Print(variables_,
+ " $name$.add(s);\n");
+ printer->Print(variables_,
+ "}\n"
+ "input.popLimit(limit);\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_mutable$) {\n"
+ " $name$_.makeImmutable();\n"
+ "}\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (get$capitalized_name$List().size() > 0) {\n"
+ " output.writeRawVarint32($tag$);\n"
+ " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+ "}\n"
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.write$capitalized_type$NoTag($name$_.get(i));\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.writeBytes($number$, $name$_.getByteString(i));\n"
+ "}\n");
+ }
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "{\n"
+ " int dataSize = 0;\n");
+ printer->Indent();
+
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " dataSize += com.google.protobuf.CodedOutputStream\n"
+ " .computeBytesSizeNoTag($name$_.getByteString(i));\n"
+ "}\n");
+
+ printer->Print(
+ "size += dataSize;\n");
+
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (!get$capitalized_name$List().isEmpty()) {\n"
+ " size += $tag_size$;\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeInt32SizeNoTag(dataSize);\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "size += $tag_size$ * get$capitalized_name$List().size();\n");
+ }
+
+ // cache the data size for packed fields.
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "$name$MemoizedSerializedSize = dataSize;\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$List()\n"
+ " .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (get$capitalized_name$Count() > 0) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+ "}\n");
+}
+
+string RepeatedImmutableStringFieldLiteGenerator::GetBoxedType() const {
+ return "String";
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.h b/src/google/protobuf/compiler/java/java_string_field_lite.h
new file mode 100644
index 00000000..9d93b307
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.h
@@ -0,0 +1,158 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Author: jonp@google.com (Jon Perlow)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ class ClassNameResolver; // name_resolver.h
+ }
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator {
+ public:
+ explicit ImmutableStringFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableStringFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ int GetNumBitsForMessage() const;
+ int GetNumBitsForBuilder() const;
+ void GenerateInterfaceMembers(io::Printer* printer) const;
+ 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 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldLiteGenerator);
+};
+
+class ImmutableStringOneofFieldLiteGenerator
+ : public ImmutableStringFieldLiteGenerator {
+ public:
+ ImmutableStringOneofFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableStringOneofFieldLiteGenerator();
+
+ private:
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutableStringFieldLiteGenerator
+ : public ImmutableFieldLiteGenerator {
+ public:
+ explicit RepeatedImmutableStringFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~RepeatedImmutableStringFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ int GetNumBitsForMessage() const;
+ int GetNumBitsForBuilder() const;
+ void GenerateInterfaceMembers(io::Printer* printer) const;
+ 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 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.cc b/src/google/protobuf/compiler/javanano/javanano_enum.cc
index f934b05f..c6e8dfe9 100644
--- a/src/google/protobuf/compiler/javanano/javanano_enum.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_enum.cc
@@ -73,13 +73,45 @@ void EnumGenerator::Generate(io::Printer* printer) {
"// enum $classname$\n",
"classname", descriptor_->name());
+ const string classname = RenameJavaKeywords(descriptor_->name());
+
// Start of container interface
+ // If generating intdefs, we use the container interface as the intdef if
+ // present. Otherwise, we just make an empty @interface parallel to the
+ // constants.
+ bool use_intdef = params_.generate_intdefs();
bool use_shell_class = params_.java_enum_style();
- if (use_shell_class) {
- printer->Print(
- "public interface $classname$ {\n",
- "classname", RenameJavaKeywords(descriptor_->name()));
+ if (use_intdef) {
+ // @IntDef annotation so tools can enforce correctness
+ // Annotations will be discarded by the compiler
+ printer->Print("@java.lang.annotation.Retention("
+ "java.lang.annotation.RetentionPolicy.SOURCE)\n"
+ "@android.support.annotation.IntDef({\n");
printer->Indent();
+ for (int i = 0; i < canonical_values_.size(); i++) {
+ const string constant_name =
+ RenameJavaKeywords(canonical_values_[i]->name());
+ if (use_shell_class) {
+ printer->Print("$classname$.$name$,\n",
+ "classname", classname,
+ "name", constant_name);
+ } else {
+ printer->Print("$name$,\n", "name", constant_name);
+ }
+ }
+ printer->Outdent();
+ printer->Print("})\n");
+ }
+ if (use_shell_class || use_intdef) {
+ printer->Print(
+ "public $at_for_intdef$interface $classname$ {\n",
+ "classname", classname,
+ "at_for_intdef", use_intdef ? "@" : "");
+ if (use_shell_class) {
+ printer->Indent();
+ } else {
+ printer->Print("}\n\n");
+ }
}
// Canonical values
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
index 8a59d323..7666db38 100644
--- a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
@@ -76,6 +76,10 @@ void SetEnumVariables(const Params& params,
internal::WireFormatLite::MakeTag(descriptor->number(),
internal::WireFormat::WireTypeForFieldType(descriptor->type())));
(*variables)["message_name"] = descriptor->containing_type()->name();
+ const EnumDescriptor* enum_type = descriptor->enum_type();
+ (*variables)["message_type_intdef"] = "@"
+ + ToJavaName(params, enum_type->name(), true,
+ enum_type->containing_type(), enum_type->file());
}
void LoadEnumValues(const Params& params,
@@ -116,8 +120,10 @@ EnumFieldGenerator::~EnumFieldGenerator() {}
void EnumFieldGenerator::
GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
- printer->Print(variables_,
- "public $type$ $name$;\n");
+ if (params_.generate_intdefs()) {
+ printer->Print(variables_, "$message_type_intdef$\n");
+ }
+ printer->Print(variables_, "public $type$ $name$;\n");
if (params_.generate_has()) {
printer->Print(variables_,
@@ -256,12 +262,22 @@ AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {}
void AccessorEnumFieldGenerator::
GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+ printer->Print(variables_, "private int $name$_;\n");
+ if (params_.generate_intdefs()) {
+ printer->Print(variables_, "$message_type_intdef$\n");
+ }
printer->Print(variables_,
- "private int $name$_;\n"
"public int get$capitalized_name$() {\n"
" return $name$_;\n"
"}\n"
- "public $message_name$ set$capitalized_name$(int value) {\n"
+ "public $message_name$ set$capitalized_name$(");
+ if (params_.generate_intdefs()) {
+ printer->Print(variables_,
+ "\n"
+ " $message_type_intdef$ ");
+ }
+ printer->Print(variables_,
+ "int value) {\n"
" $name$_ = value;\n"
" $set_has$;\n"
" return this;\n"
@@ -499,6 +515,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
}
void RepeatedEnumFieldGenerator::
+GenerateFixClonedCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null && this.$name$.length > 0) {\n"
+ " cloned.$name$ = this.$name$.clone();\n"
+ "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!com.google.protobuf.nano.InternalNano.equals(\n"
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.h b/src/google/protobuf/compiler/javanano/javanano_enum_field.h
index 00adc61f..b94790d6 100644
--- a/src/google/protobuf/compiler/javanano/javanano_enum_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.h
@@ -106,6 +106,7 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCodeCode(io::Printer* printer) const;
+ void GenerateFixClonedCode(io::Printer* printer) const;
private:
void GenerateRepeatedDataSizeCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.cc b/src/google/protobuf/compiler/javanano/javanano_extension.cc
index 754ed550..0b9d1d8d 100644
--- a/src/google/protobuf/compiler/javanano/javanano_extension.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_extension.cc
@@ -140,7 +140,7 @@ void ExtensionGenerator::Generate(io::Printer* printer) const {
" com.google.protobuf.nano.Extension.create$repeated$$ext_type$(\n"
" com.google.protobuf.nano.Extension.$type$,\n"
" $class$.class,\n"
- " $tag_params$);\n");
+ " $tag_params$L);\n");
}
} // namespace javanano
diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc
index e3e4cefe..85257f3f 100644
--- a/src/google/protobuf/compiler/javanano/javanano_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_field.cc
@@ -36,6 +36,7 @@
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
#include <google/protobuf/compiler/javanano/javanano_enum_field.h>
+#include <google/protobuf/compiler/javanano/javanano_map_field.h>
#include <google/protobuf/compiler/javanano/javanano_message_field.h>
#include <google/protobuf/stubs/common.h>
@@ -97,12 +98,24 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
if (field->is_repeated()) {
switch (java_type) {
case JAVATYPE_MESSAGE:
- return new RepeatedMessageFieldGenerator(field, params);
+ if (IsMapEntry(field->message_type())) {
+ return new MapFieldGenerator(field, params);
+ } else {
+ return new RepeatedMessageFieldGenerator(field, params);
+ }
case JAVATYPE_ENUM:
return new RepeatedEnumFieldGenerator(field, params);
default:
return new RepeatedPrimitiveFieldGenerator(field, params);
}
+ } else if (field->containing_oneof()) {
+ switch (java_type) {
+ case JAVATYPE_MESSAGE:
+ return new MessageOneofFieldGenerator(field, params);
+ case JAVATYPE_ENUM:
+ default:
+ return new PrimitiveOneofFieldGenerator(field, params);
+ }
} else if (params.optional_field_accessors() && field->is_optional()
&& java_type != JAVATYPE_MESSAGE) {
// We need a has-bit for each primitive/enum field because their default
@@ -137,6 +150,59 @@ const FieldGenerator& FieldGeneratorMap::get(
return *field_generators_[field->index()];
}
+void SetCommonOneofVariables(const FieldDescriptor* descriptor,
+ map<string, string>* variables) {
+ (*variables)["oneof_name"] =
+ UnderscoresToCamelCase(descriptor->containing_oneof());
+ (*variables)["oneof_capitalized_name"] =
+ UnderscoresToCapitalizedCamelCase(descriptor->containing_oneof());
+ (*variables)["oneof_index"] =
+ SimpleItoa(descriptor->containing_oneof()->index());
+ (*variables)["set_oneof_case"] =
+ "this." + (*variables)["oneof_name"] +
+ "Case_ = " + SimpleItoa(descriptor->number());
+ (*variables)["clear_oneof_case"] =
+ "this." + (*variables)["oneof_name"] + "Case_ = 0";
+ (*variables)["has_oneof_case"] =
+ "this." + (*variables)["oneof_name"] + "Case_ == " +
+ SimpleItoa(descriptor->number());
+}
+
+void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
+ const map<string, string>& variables,
+ io::Printer* printer) {
+ if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
+ printer->Print(variables,
+ "if (this.has$capitalized_name$()) {\n"
+ " if (!java.util.Arrays.equals((byte[]) this.$oneof_name$_,\n"
+ " (byte[]) other.$oneof_name$_)) {\n"
+ " return false;\n"
+ " }\n"
+ "}\n");
+ } else {
+ printer->Print(variables,
+ "if (this.has$capitalized_name$()) {\n"
+ " if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n"
+ " return false;\n"
+ " }\n"
+ "}\n");
+ }
+}
+
+void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
+ const map<string, string>& variables,
+ io::Printer* printer) {
+ if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
+ printer->Print(variables,
+ "result = 31 * result + ($has_oneof_case$\n"
+ " ? java.util.Arrays.hashCode((byte[]) this.$oneof_name$_) : 0);\n");
+ } else {
+ printer->Print(variables,
+ "result = 31 * result +\n"
+ " ($has_oneof_case$ ? this.$oneof_name$_.hashCode() : 0);\n");
+ }
+}
+
} // namespace javanano
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h
index 6170c2c0..57c221f4 100644
--- a/src/google/protobuf/compiler/javanano/javanano_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_field.h
@@ -35,6 +35,7 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__
+#include <map>
#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
@@ -82,6 +83,7 @@ class FieldGenerator {
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
virtual void GenerateHashCodeCode(io::Printer* printer) const = 0;
+ virtual void GenerateFixClonedCode(io::Printer* printer) const {}
protected:
const Params& params_;
@@ -111,6 +113,15 @@ class FieldGeneratorMap {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
};
+void SetCommonOneofVariables(const FieldDescriptor* descriptor,
+ map<string, string>* variables);
+void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
+ const map<string, string>& variables,
+ io::Printer* printer);
+void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
+ const map<string, string>& variables,
+ io::Printer* printer);
+
} // namespace javanano
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc
index b5fbcd5f..a33eba1b 100644
--- a/src/google/protobuf/compiler/javanano/javanano_generator.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc
@@ -67,8 +67,15 @@ void UpdateParamsRecursively(Params& params,
file->name(), file->options().java_outer_classname());
}
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";
+ }
params.set_java_package(
- file->name(), file->options().java_package());
+ file->name(), result);
}
if (file->options().has_java_multiple_files()) {
params.set_java_multiple_files(
@@ -152,6 +159,12 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file,
params.set_ignore_services(option_value == "true");
} else if (option_name == "parcelable_messages") {
params.set_parcelable_messages(option_value == "true");
+ } else if (option_name == "generate_clone") {
+ params.set_generate_clone(option_value == "true");
+ } else if (option_name == "generate_intdefs") {
+ params.set_generate_intdefs(option_value == "true");
+ } else if (option_name == "generate_clear") {
+ params.set_generate_clear(option_value == "true");
} else {
*error = "Ignore unknown javanano generator option: " + option_name;
}
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
index 2149418a..5465655f 100644
--- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
@@ -154,6 +154,14 @@ string UnderscoresToCamelCase(const MethodDescriptor* method) {
return UnderscoresToCamelCaseImpl(method->name(), false);
}
+string UnderscoresToCamelCase(const OneofDescriptor* oneof) {
+ return UnderscoresToCamelCaseImpl(oneof->name(), false);
+}
+
+string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof) {
+ return UnderscoresToCamelCaseImpl(oneof->name(), true);
+}
+
string RenameJavaKeywords(const string& input) {
return sRenameKeywords.RenameJavaKeywordsImpl(input);
}
@@ -192,6 +200,14 @@ string FileJavaPackage(const Params& params, const FileDescriptor* file) {
if (!result.empty()) result += '.';
result += file->package();
}
+
+ if (!file->options().javanano_use_deprecated_package()) {
+ if (!result.empty()) {
+ result += ".";
+ }
+ result += "nano";
+ }
+
return result;
}
}
@@ -560,6 +576,17 @@ void SetBitOperationVariables(const string name,
(*variables)["different_" + name] = GenerateDifferentBit(bitIndex);
}
+bool HasMapField(const Descriptor* descriptor) {
+ for (int i = 0; i < descriptor->field_count(); ++i) {
+ const FieldDescriptor* field = descriptor->field(i);
+ if (field->type() == FieldDescriptor::TYPE_MESSAGE &&
+ IsMapEntry(field->message_type())) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace javanano
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h
index 29310743..014c85ae 100644
--- a/src/google/protobuf/compiler/javanano/javanano_helpers.h
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.h
@@ -54,7 +54,9 @@ extern const char kThinSeparator[];
// Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes
// "fooBarBaz" or "FooBarBaz", respectively.
string UnderscoresToCamelCase(const FieldDescriptor* field);
+string UnderscoresToCamelCase(const OneofDescriptor* oneof);
string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field);
+string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof);
// Appends an "_" to the end of a field where the name is a reserved java
// keyword. For example int32 public = 1 will generate int public_.
@@ -181,6 +183,14 @@ string GenerateDifferentBit(int bit_index);
void SetBitOperationVariables(const string name,
int bitIndex, map<string, string>* variables);
+inline bool IsMapEntry(const Descriptor* descriptor) {
+ // TODO(liujisi): Add an option to turn on maps for proto2 syntax as well.
+ return descriptor->options().map_entry() &&
+ descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+bool HasMapField(const Descriptor* descriptor);
+
} // namespace javanano
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/google/protobuf/compiler/javanano/javanano_map_field.cc
new file mode 100644
index 00000000..83b2b0ce
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_map_field.cc
@@ -0,0 +1,186 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/javanano/javanano_map_field.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+namespace {
+
+string TypeName(const Params& params, const FieldDescriptor* field,
+ bool boxed) {
+ JavaType java_type = GetJavaType(field);
+ switch (java_type) {
+ case JAVATYPE_MESSAGE:
+ return ClassName(params, field->message_type());
+ case JAVATYPE_INT:
+ case JAVATYPE_LONG:
+ case JAVATYPE_FLOAT:
+ case JAVATYPE_DOUBLE:
+ case JAVATYPE_BOOLEAN:
+ case JAVATYPE_STRING:
+ case JAVATYPE_BYTES:
+ case JAVATYPE_ENUM:
+ if (boxed) {
+ return BoxedPrimitiveTypeName(java_type);
+ } else {
+ return PrimitiveTypeName(java_type);
+ }
+ // No default because we want the compiler to complain if any new JavaTypes
+ // are added..
+ }
+
+ GOOGLE_LOG(FATAL) << "should not reach here.";
+ return "";
+}
+
+const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) {
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+ const Descriptor* message = descriptor->message_type();
+ GOOGLE_CHECK(message->options().map_entry());
+ return message->FindFieldByName("key");
+}
+
+const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) {
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+ const Descriptor* message = descriptor->message_type();
+ GOOGLE_CHECK(message->options().map_entry());
+ return message->FindFieldByName("value");
+}
+
+void SetMapVariables(const Params& params,
+ const FieldDescriptor* descriptor, map<string, string>* variables) {
+ const FieldDescriptor* key = KeyField(descriptor);
+ const FieldDescriptor* value = ValueField(descriptor);
+ (*variables)["name"] =
+ RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
+ (*variables)["number"] = SimpleItoa(descriptor->number());
+ (*variables)["key_type"] = TypeName(params, key, false);
+ (*variables)["boxed_key_type"] = TypeName(params,key, true);
+ (*variables)["key_desc_type"] =
+ "TYPE_" + ToUpper(FieldDescriptor::TypeName(key->type()));
+ (*variables)["key_tag"] = SimpleItoa(internal::WireFormat::MakeTag(key));
+ (*variables)["value_type"] = TypeName(params, value, false);
+ (*variables)["boxed_value_type"] = TypeName(params, value, true);
+ (*variables)["value_desc_type"] =
+ "TYPE_" + ToUpper(FieldDescriptor::TypeName(value->type()));
+ (*variables)["value_tag"] = SimpleItoa(internal::WireFormat::MakeTag(value));
+ (*variables)["type_parameters"] =
+ (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
+ (*variables)["value_default"] =
+ value->type() == FieldDescriptor::TYPE_MESSAGE
+ ? "new " + (*variables)["value_type"] + "()"
+ : "null";
+}
+} // namespace
+
+// ===================================================================
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+ const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetMapVariables(params, descriptor, &variables_);
+}
+
+MapFieldGenerator::~MapFieldGenerator() {}
+
+void MapFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+ printer->Print(variables_,
+ "public java.util.Map<$type_parameters$> $name$;\n");
+}
+
+void MapFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$ = null;\n");
+}
+
+void MapFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "this.$name$ = com.google.protobuf.nano.InternalNano.mergeMapEntry(\n"
+ " input, this.$name$, mapFactory,\n"
+ " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
+ " com.google.protobuf.nano.InternalNano.$value_desc_type$,\n"
+ " $value_default$,\n"
+ " $key_tag$, $value_tag$);\n"
+ "\n");
+}
+
+void MapFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null) {\n"
+ " com.google.protobuf.nano.InternalNano.serializeMapField(\n"
+ " output, this.$name$, $number$,\n"
+ " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
+ " com.google.protobuf.nano.InternalNano.$value_desc_type$);\n"
+ "}\n");
+}
+
+void MapFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null) {\n"
+ " size += com.google.protobuf.nano.InternalNano.computeMapFieldSize(\n"
+ " this.$name$, $number$,\n"
+ " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
+ " com.google.protobuf.nano.InternalNano.$value_desc_type$);\n"
+ "}\n");
+}
+
+void MapFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!com.google.protobuf.nano.InternalNano.equals(\n"
+ " this.$name$, other.$name$)) {\n"
+ " return false;\n"
+ "}\n");
+}
+
+void MapFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = 31 * result +\n"
+ " com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.h b/src/google/protobuf/compiler/javanano/javanano_map_field.h
new file mode 100644
index 00000000..c01bde38
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_map_field.h
@@ -0,0 +1,70 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
+
+#include <map>
+#include <string>
+#include <vector>
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class MapFieldGenerator : public FieldGenerator {
+ public:
+ explicit MapFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params);
+ ~MapFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+ void GenerateClearCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc
index 7c52ca31..a41da5ae 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_message.cc
@@ -90,6 +90,7 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
// Generate static members for all nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// TODO(kenton): Reuse MessageGenerator objects?
+ if (IsMapEntry(descriptor_->nested_type(i))) continue;
MessageGenerator(descriptor_->nested_type(i), params_)
.GenerateStaticVariables(printer);
}
@@ -100,6 +101,7 @@ void MessageGenerator::GenerateStaticVariableInitializers(
// Generate static member initializers for all nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// TODO(kenton): Reuse MessageGenerator objects?
+ if (IsMapEntry(descriptor_->nested_type(i))) continue;
MessageGenerator(descriptor_->nested_type(i), params_)
.GenerateStaticVariableInitializers(printer);
}
@@ -134,21 +136,37 @@ void MessageGenerator::Generate(io::Printer* printer) {
}
if (params_.store_unknown_fields() && params_.parcelable_messages()) {
printer->Print(
- " com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$> {\n",
+ " com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$>",
"classname", descriptor_->name());
} else if (params_.store_unknown_fields()) {
printer->Print(
- " com.google.protobuf.nano.ExtendableMessageNano<$classname$> {\n",
+ " com.google.protobuf.nano.ExtendableMessageNano<$classname$>",
"classname", descriptor_->name());
} else if (params_.parcelable_messages()) {
printer->Print(
- " com.google.protobuf.nano.android.ParcelableMessageNano {\n");
+ " com.google.protobuf.nano.android.ParcelableMessageNano");
} else {
printer->Print(
- " com.google.protobuf.nano.MessageNano {\n");
+ " com.google.protobuf.nano.MessageNano");
+ }
+ if (params_.generate_clone()) {
+ printer->Print(" implements java.lang.Cloneable {\n");
+ } else {
+ printer->Print(" {\n");
}
printer->Indent();
+ if (params_.parcelable_messages()) {
+ printer->Print(
+ "\n"
+ "// Used by Parcelable\n"
+ "@SuppressWarnings({\"unused\"})\n"
+ "public static final android.os.Parcelable.Creator<$classname$> CREATOR =\n"
+ " new com.google.protobuf.nano.android.ParcelableMessageNanoCreator<\n"
+ " $classname$>($classname$.class);\n",
+ "classname", descriptor_->name());
+ }
+
// Nested types and extensions
for (int i = 0; i < descriptor_->extension_count(); i++) {
ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer);
@@ -159,9 +177,44 @@ void MessageGenerator::Generate(io::Printer* printer) {
}
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ if (IsMapEntry(descriptor_->nested_type(i))) continue;
MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
}
+ // oneof
+ map<string, string> vars;
+ vars["message_name"] = descriptor_->name();
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
+ vars["oneof_name"] = UnderscoresToCamelCase(oneof_desc);
+ vars["oneof_capitalized_name"] =
+ UnderscoresToCapitalizedCamelCase(oneof_desc);
+ vars["oneof_index"] = SimpleItoa(oneof_desc->index());
+ // Oneof Constants
+ for (int j = 0; j < oneof_desc->field_count(); j++) {
+ const FieldDescriptor* field = oneof_desc->field(j);
+ vars["number"] = SimpleItoa(field->number());
+ vars["cap_field_name"] = ToUpper(field->name());
+ printer->Print(vars,
+ "public static final int $cap_field_name$_FIELD_NUMBER = $number$;\n");
+ }
+ // oneofCase_ and oneof_
+ printer->Print(vars,
+ "private int $oneof_name$Case_ = 0;\n"
+ "private java.lang.Object $oneof_name$_;\n");
+ printer->Print(vars,
+ "public int get$oneof_capitalized_name$Case() {\n"
+ " return this.$oneof_name$Case_;\n"
+ "}\n");
+ // Oneof clear
+ printer->Print(vars,
+ "public $message_name$ clear$oneof_capitalized_name$() {\n"
+ " this.$oneof_name$Case_ = 0;\n"
+ " this.$oneof_name$_ = null;\n"
+ " return this;\n"
+ "}\n");
+ }
+
// Lazy initialization of otherwise static final fields can help prevent the
// class initializer from being generated. We want to prevent it because it
// stops ProGuard from inlining any methods in this class into call sites and
@@ -251,20 +304,28 @@ void MessageGenerator::Generate(io::Printer* printer) {
}
printer->Print("}\n");
} else {
+ printer->Print(
+ "\n"
+ "public $classname$() {\n",
+ "classname", descriptor_->name());
if (params_.generate_clear()) {
- printer->Print(
- "\n"
- "public $classname$() {\n"
- " clear();\n"
- "}\n",
- "classname", descriptor_->name());
+ printer->Print(" clear();\n");
+ } else {
+ printer->Indent();
+ GenerateFieldInitializers(printer);
+ printer->Outdent();
}
+ printer->Print("}\n");
}
// Other methods in this class
GenerateClear(printer);
+ if (params_.generate_clone()) {
+ GenerateClone(printer);
+ }
+
if (params_.generate_equals()) {
GenerateEquals(printer);
GenerateHashCode(printer);
@@ -342,6 +403,11 @@ void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
"classname", descriptor_->name());
printer->Indent();
+ if (HasMapField(descriptor_)) {
+ printer->Print(
+ "com.google.protobuf.nano.MapFactories.MapFactory mapFactory =\n"
+ " com.google.protobuf.nano.MapFactories.getMapFactory();\n");
+ }
printer->Print(
"while (true) {\n");
@@ -453,6 +519,15 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
"classname", descriptor_->name());
printer->Indent();
+ GenerateFieldInitializers(printer);
+
+ printer->Outdent();
+ printer->Print(
+ " return this;\n"
+ "}\n");
+}
+
+void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) {
// Clear bit fields.
int totalInts = (field_generators_.total_bits() + 31) / 32;
for (int i = 0; i < totalInts; i++) {
@@ -466,16 +541,46 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
field_generators_.get(field).GenerateClearCode(printer);
}
+ // Clear oneofs.
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ printer->Print(
+ "clear$oneof_capitalized_name$();\n",
+ "oneof_capitalized_name", UnderscoresToCapitalizedCamelCase(
+ descriptor_->oneof_decl(i)));
+ }
+
// Clear unknown fields.
if (params_.store_unknown_fields()) {
printer->Print("unknownFieldData = null;\n");
}
+ printer->Print("cachedSize = -1;\n");
+}
+
+void MessageGenerator::GenerateClone(io::Printer* printer) {
+ printer->Print(
+ "@Override\n"
+ "public $classname$ clone() {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+
+ printer->Print(
+ "$classname$ cloned;\n"
+ "try {\n"
+ " cloned = ($classname$) super.clone();\n"
+ "} catch (java.lang.CloneNotSupportedException e) {\n"
+ " throw new java.lang.AssertionError(e);\n"
+ "}\n",
+ "classname", descriptor_->name());
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i)).GenerateFixClonedCode(printer);
+ }
printer->Outdent();
printer->Print(
- " cachedSize = -1;\n"
- " return this;\n"
- "}\n");
+ " return cloned;\n"
+ "}\n"
+ "\n");
}
void MessageGenerator::GenerateEquals(io::Printer* printer) {
@@ -501,6 +606,16 @@ void MessageGenerator::GenerateEquals(io::Printer* printer) {
"$classname$ other = ($classname$) o;\n",
"classname", descriptor_->name());
+ // Checking oneof case before checking each oneof field.
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
+ printer->Print(
+ "if (this.$oneof_name$Case_ != other.$oneof_name$Case_) {\n"
+ " return false;\n"
+ "}\n",
+ "oneof_name", UnderscoresToCamelCase(oneof_desc));
+ }
+
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
field_generators_.get(field).GenerateEqualsCode(printer);
@@ -508,7 +623,11 @@ void MessageGenerator::GenerateEquals(io::Printer* printer) {
if (params_.store_unknown_fields()) {
printer->Print(
- "return unknownFieldDataEquals(other);\n");
+ "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n"
+ " return other.unknownFieldData == null || other.unknownFieldData.isEmpty();\n"
+ "} else {\n"
+ " return unknownFieldData.equals(other.unknownFieldData);\n"
+ "}");
} else {
printer->Print(
"return true;\n");
@@ -538,7 +657,9 @@ void MessageGenerator::GenerateHashCode(io::Printer* printer) {
if (params_.store_unknown_fields()) {
printer->Print(
- "result = 31 * result + unknownFieldDataHashCode();\n");
+ "result = 31 * result + \n"
+ " (unknownFieldData == null || unknownFieldData.isEmpty() ? 0 : \n"
+ " unknownFieldData.hashCode());\n");
}
printer->Print("return result;\n");
diff --git a/src/google/protobuf/compiler/javanano/javanano_message.h b/src/google/protobuf/compiler/javanano/javanano_message.h
index 6f25a3a0..281ec64f 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message.h
+++ b/src/google/protobuf/compiler/javanano/javanano_message.h
@@ -77,8 +77,10 @@ class MessageGenerator {
const FieldDescriptor* field);
void GenerateClear(io::Printer* printer);
+ void GenerateFieldInitializers(io::Printer* printer);
void GenerateEquals(io::Printer* printer);
void GenerateHashCode(io::Printer* printer);
+ void GenerateClone(io::Printer* printer);
const Params& params_;
const Descriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
index a46081d0..d1d04b52 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
@@ -127,6 +127,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
}
void MessageFieldGenerator::
+GenerateFixClonedCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null) {\n"
+ " cloned.$name$ = this.$name$.clone();\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
"if (this.$name$ == null) { \n"
@@ -146,12 +154,95 @@ GenerateHashCodeCode(io::Printer* printer) const {
"result = 31 * result +\n"
" (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
}
+// ===================================================================
+
+MessageOneofFieldGenerator::MessageOneofFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetMessageVariables(params, descriptor, &variables_);
+ SetCommonOneofVariables(descriptor, &variables_);
+}
+
+MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
+
+void MessageOneofFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+ printer->Print(variables_,
+ "public boolean has$capitalized_name$() {\n"
+ " return $has_oneof_case$;\n"
+ "}\n"
+ "public $type$ get$capitalized_name$() {\n"
+ " if ($has_oneof_case$) {\n"
+ " return ($type$) this.$oneof_name$_;\n"
+ " }\n"
+ " return null;\n"
+ "}\n"
+ "public $message_name$ set$capitalized_name$($type$ value) {\n"
+ " if (value == null) { throw new java.lang.NullPointerException(); }\n"
+ " $set_oneof_case$;\n"
+ " this.$oneof_name$_ = value;\n"
+ " return this;\n"
+ "}\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+ // No clear method for oneof fields.
+}
+
+void MessageOneofFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!($has_oneof_case$)) {\n"
+ " this.$oneof_name$_ = new $type$();\n"
+ "}\n"
+ "input.readMessage(\n"
+ " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
+ "$set_oneof_case$;\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case$) {\n"
+ " output.writeMessage($number$,\n"
+ " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
+ "}\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case$) {\n"
+ " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .computeMessageSize($number$,\n"
+ " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
+ "}\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateFixClonedCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$oneof_name$ != null) {\n"
+ " cloned.$oneof_name$ = this.$oneof_name$.clone();\n"
+ "}\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ GenerateOneofFieldEquals(descriptor_, variables_, printer);
+}
+
+void MessageOneofFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+ GenerateOneofFieldHashCode(descriptor_, variables_, printer);
+}
// ===================================================================
-RepeatedMessageFieldGenerator::
-RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
- : FieldGenerator(params), descriptor_(descriptor) {
+RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
SetMessageVariables(params, descriptor, &variables_);
}
@@ -238,6 +329,19 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
}
void RepeatedMessageFieldGenerator::
+GenerateFixClonedCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null && this.$name$.length > 0) {\n"
+ " cloned.$name$ = new $type$[this.$name$.length];\n"
+ " for (int i = 0; i < this.$name$.length; i++) {\n"
+ " if (this.$name$[i] != null) {\n"
+ " cloned.$name$[i] = this.$name$[i].clone();\n"
+ " }\n"
+ " }\n"
+ "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!com.google.protobuf.nano.InternalNano.equals(\n"
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h
index 5d35fd24..e074735c 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.h
@@ -58,6 +58,7 @@ class MessageFieldGenerator : public FieldGenerator {
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCodeCode(io::Printer* printer) const;
+ void GenerateFixClonedCode(io::Printer* printer) const;
private:
const FieldDescriptor* descriptor_;
@@ -66,6 +67,29 @@ class MessageFieldGenerator : public FieldGenerator {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
};
+class MessageOneofFieldGenerator : public FieldGenerator {
+ public:
+ explicit MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+ const Params& params);
+ ~MessageOneofFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+ void GenerateClearCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCodeCode(io::Printer* printer) const;
+ void GenerateFixClonedCode(io::Printer* printer) const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
+};
+
class RepeatedMessageFieldGenerator : public FieldGenerator {
public:
explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
@@ -80,6 +104,7 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCodeCode(io::Printer* printer) const;
+ void GenerateFixClonedCode(io::Printer* printer) const;
private:
const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/javanano/javanano_params.h b/src/google/protobuf/compiler/javanano/javanano_params.h
index 4691f360..e3b4bb93 100644
--- a/src/google/protobuf/compiler/javanano/javanano_params.h
+++ b/src/google/protobuf/compiler/javanano/javanano_params.h
@@ -66,6 +66,8 @@ class Params {
bool parcelable_messages_;
bool reftypes_primitive_enums_;
bool generate_clear_;
+ bool generate_clone_;
+ bool generate_intdefs_;
public:
Params(const string & base_name) :
@@ -81,7 +83,9 @@ class Params {
ignore_services_(false),
parcelable_messages_(false),
reftypes_primitive_enums_(false),
- generate_clear_(true) {
+ generate_clear_(true),
+ generate_clone_(false),
+ generate_intdefs_(false) {
}
const string& base_name() const {
@@ -231,6 +235,20 @@ class Params {
bool generate_clear() const {
return generate_clear_;
}
+
+ void set_generate_clone(bool value) {
+ generate_clone_ = value;
+ }
+ bool generate_clone() const {
+ return generate_clone_;
+ }
+
+ void set_generate_intdefs(bool value) {
+ generate_intdefs_ = value;
+ }
+ bool generate_intdefs() const {
+ return generate_intdefs_;
+ }
};
} // namespace javanano
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
index a3bc3a84..978abf2c 100644
--- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
@@ -155,28 +155,6 @@ int FixedSize(FieldDescriptor::Type type) {
return -1;
}
-// Return true if the type is a that has variable length
-// for instance String's.
-bool IsVariableLenType(JavaType type) {
- switch (type) {
- case JAVATYPE_INT : return false;
- case JAVATYPE_LONG : return false;
- case JAVATYPE_FLOAT : return false;
- case JAVATYPE_DOUBLE : return false;
- case JAVATYPE_BOOLEAN: return false;
- case JAVATYPE_STRING : return true;
- case JAVATYPE_BYTES : return true;
- case JAVATYPE_ENUM : return false;
- case JAVATYPE_MESSAGE: return true;
-
- // No default because we want the compiler to complain if any new
- // JavaTypes are added.
- }
-
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return false;
-}
-
bool AllAscii(const string& text) {
for (int i = 0; i < text.size(); i++) {
if ((text[i] & 0x80) != 0) {
@@ -186,6 +164,7 @@ bool AllAscii(const string& text) {
return true;
}
+
void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params,
map<string, string>* variables) {
(*variables)["name"] =
@@ -385,6 +364,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
}
}
+void RepeatedPrimitiveFieldGenerator::
+GenerateFixClonedCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null && this.$name$.length > 0) {\n"
+ " cloned.$name$ = this.$name$.clone();\n"
+ "}\n");
+}
+
void PrimitiveFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
// We define equality as serialized form equality. If generate_has(),
@@ -706,8 +693,79 @@ GenerateHashCodeCode(io::Printer* printer) const {
// ===================================================================
-RepeatedPrimitiveFieldGenerator::
-RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetPrimitiveVariables(descriptor, params, &variables_);
+ SetCommonOneofVariables(descriptor, &variables_);
+}
+
+PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
+
+void PrimitiveOneofFieldGenerator::GenerateMembers(
+ io::Printer* printer, bool /*unused lazy_init*/) const {
+ printer->Print(variables_,
+ "public boolean has$capitalized_name$() {\n"
+ " return $has_oneof_case$;\n"
+ "}\n"
+ "public $type$ get$capitalized_name$() {\n"
+ " if ($has_oneof_case$) {\n"
+ " return ($type$) ($boxed_type$) this.$oneof_name$_;\n"
+ " }\n"
+ " return $default$;\n"
+ "}\n"
+ "public $message_name$ set$capitalized_name$($type$ value) {\n"
+ " $set_oneof_case$;\n"
+ " this.$oneof_name$_ = value;\n"
+ " return this;\n"
+ "}\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateClearCode(
+ io::Printer* printer) const {
+ // No clear method for oneof fields.
+}
+
+void PrimitiveOneofFieldGenerator::GenerateMergingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "this.$oneof_name$_ = input.read$capitalized_type$();\n"
+ "$set_oneof_case$;\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateSerializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case$) {\n"
+ " output.write$capitalized_type$(\n"
+ " $number$, ($boxed_type$) this.$oneof_name$_);\n"
+ "}\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateSerializedSizeCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case$) {\n"
+ " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .compute$capitalized_type$Size(\n"
+ " $number$, ($boxed_type$) this.$oneof_name$_);\n"
+ "}\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateEqualsCode(
+ io::Printer* printer) const {
+ GenerateOneofFieldEquals(descriptor_, variables_, printer);
+}
+
+void PrimitiveOneofFieldGenerator::GenerateHashCodeCode(
+ io::Printer* printer) const {
+ GenerateOneofFieldHashCode(descriptor_, variables_, printer);
+}
+
+// ===================================================================
+
+RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params)
: FieldGenerator(params), descriptor_(descriptor) {
SetPrimitiveVariables(descriptor, params, &variables_);
}
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
index c04a19b7..a01981dd 100644
--- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
@@ -47,7 +47,7 @@ namespace javanano {
class PrimitiveFieldGenerator : public FieldGenerator {
public:
explicit PrimitiveFieldGenerator(
- const FieldDescriptor* descriptor, const Params &params);
+ const FieldDescriptor* descriptor, const Params& params);
~PrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -94,9 +94,32 @@ class AccessorPrimitiveFieldGenerator : public FieldGenerator {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorPrimitiveFieldGenerator);
};
+class PrimitiveOneofFieldGenerator : public FieldGenerator {
+ public:
+ explicit PrimitiveOneofFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params);
+ ~PrimitiveOneofFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+ void GenerateClearCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
+};
+
class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
public:
- explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
+ explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Params& params);
~RepeatedPrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -108,6 +131,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCodeCode(io::Printer* printer) const;
+ void GenerateFixClonedCode(io::Printer* printer) const;
private:
void GenerateRepeatedDataSizeCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
index 931b8fa3..4815a726 100644
--- a/src/google/protobuf/compiler/main.cc
+++ b/src/google/protobuf/compiler/main.cc
@@ -36,6 +36,8 @@
#include <google/protobuf/compiler/java/java_generator.h>
#include <google/protobuf/compiler/javanano/javanano_generator.h>
#include <google/protobuf/compiler/ruby/ruby_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_generator.h>
+#include <google/protobuf/compiler/objectivec/objectivec_generator.h>
int main(int argc, char* argv[]) {
@@ -68,5 +70,15 @@ int main(int argc, char* argv[]) {
cli.RegisterGenerator("--ruby_out", &rb_generator,
"Generate Ruby source file.");
+ // CSharp
+ google::protobuf::compiler::csharp::Generator csharp_generator;
+ cli.RegisterGenerator("--csharp_out", &csharp_generator,
+ "Generate C# source file.");
+
+ // Objective C
+ google::protobuf::compiler::objectivec::ObjectiveCGenerator objc_generator;
+ cli.RegisterGenerator("--objc_out", &objc_generator,
+ "Generate Objective C header and source.");
+
return cli.Run(argc, argv);
}
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
index e7d5117e..98261431 100644
--- a/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -133,10 +133,10 @@ bool MockCodeGenerator::Generate(
*error = "Saw message type MockCodeGenerator_Error.";
return false;
} else if (command == "Exit") {
- cerr << "Saw message type MockCodeGenerator_Exit." << endl;
+ std::cerr << "Saw message type MockCodeGenerator_Exit." << std::endl;
exit(123);
} else if (command == "Abort") {
- cerr << "Saw message type MockCodeGenerator_Abort." << endl;
+ std::cerr << "Saw message type MockCodeGenerator_Abort." << std::endl;
abort();
} else if (command == "HasSourceCodeInfo") {
FileDescriptorProto file_descriptor_proto;
@@ -144,8 +144,8 @@ bool MockCodeGenerator::Generate(
bool has_source_code_info =
file_descriptor_proto.has_source_code_info() &&
file_descriptor_proto.source_code_info().location_size() > 0;
- cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: "
- << has_source_code_info << "." << endl;
+ std::cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: "
+ << has_source_code_info << "." << std::endl;
abort();
} else {
GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
new file mode 100644
index 00000000..d6f01c60
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
@@ -0,0 +1,198 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor)
+ : descriptor_(descriptor),
+ name_(EnumName(descriptor_)) {
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ const EnumValueDescriptor* value = descriptor_->value(i);
+ const EnumValueDescriptor* canonical_value =
+ descriptor_->FindValueByNumber(value->number());
+
+ if (value == canonical_value) {
+ base_values_.push_back(value);
+ }
+ all_values_.push_back(value);
+ }
+}
+
+EnumGenerator::~EnumGenerator() {}
+
+void EnumGenerator::GenerateHeader(io::Printer* printer) {
+ string enum_comments;
+ SourceLocation location;
+ if (descriptor_->GetSourceLocation(&location)) {
+ enum_comments = BuildCommentsString(location);
+ } else {
+ enum_comments = "";
+ }
+
+ printer->Print(
+ "#pragma mark - Enum $name$\n"
+ "\n",
+ "name", name_);
+
+ printer->Print("$comments$typedef GPB_ENUM($name$) {\n",
+ "comments", enum_comments,
+ "name", name_);
+ printer->Indent();
+
+ if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ // Include the unknown value.
+ printer->Print(
+ "$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n",
+ "name", name_);
+ }
+
+ for (int i = 0; i < all_values_.size(); i++) {
+ SourceLocation location;
+ if (all_values_[i]->GetSourceLocation(&location)) {
+ string comments = BuildCommentsString(location).c_str();
+ if (comments.length() > 0) {
+ if (i > 0) {
+ printer->Print("\n");
+ }
+ printer->Print(comments.c_str());
+ }
+ }
+
+ printer->Print(
+ "$name$ = $value$,\n",
+ "name", EnumValueName(all_values_[i]),
+ "value", SimpleItoa(all_values_[i]->number()));
+ }
+ printer->Outdent();
+ printer->Print(
+ "};\n"
+ "\n"
+ "GPBEnumDescriptor *$name$_EnumDescriptor(void);\n"
+ "\n"
+ "BOOL $name$_IsValidValue(int32_t value);\n"
+ "\n",
+ "name", name_);
+}
+
+void EnumGenerator::GenerateSource(io::Printer* printer) {
+ printer->Print(
+ "#pragma mark - Enum $name$\n"
+ "\n",
+ "name", name_);
+
+ printer->Print(
+ "GPBEnumDescriptor *$name$_EnumDescriptor(void) {\n"
+ " static GPBEnumDescriptor *descriptor = NULL;\n"
+ " if (!descriptor) {\n"
+ " static GPBMessageEnumValueDescription values[] = {\n",
+ "name", name_);
+ printer->Indent();
+ printer->Indent();
+ printer->Indent();
+
+ // Note: For the TextFormat decode info, we can't use the enum value as
+ // the key because protocol buffer enums have 'allow_alias', which lets
+ // a value be used more than once. Instead, the index into the list of
+ // enum value descriptions is used. Note: start with -1 so the first one
+ // will be zero.
+ TextFormatDecodeData text_format_decode_data;
+ int enum_value_description_key = -1;
+
+ for (int i = 0; i < all_values_.size(); i++) {
+ ++enum_value_description_key;
+ string short_name(EnumValueShortName(all_values_[i]));
+ printer->Print("{ .name = \"$short_name$\", .number = $name$ },\n",
+ "short_name", short_name,
+ "name", EnumValueName(all_values_[i]));
+ if (UnCamelCaseEnumShortName(short_name) != all_values_[i]->name()) {
+ text_format_decode_data.AddString(enum_value_description_key, short_name,
+ all_values_[i]->name());
+ }
+ }
+ printer->Outdent();
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(" };\n");
+ if (text_format_decode_data.num_entries() == 0) {
+ printer->Print(
+ " descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
+ " values:values\n"
+ " valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)\n"
+ " enumVerifier:$name$_IsValidValue];\n",
+ "name", name_);
+ } else {
+ printer->Print(
+ " static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
+ " descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
+ " values:values\n"
+ " valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)\n"
+ " enumVerifier:$name$_IsValidValue\n"
+ " extraTextFormatInfo:extraTextFormatInfo];\n",
+ "name", name_,
+ "extraTextFormatInfo", CEscape(text_format_decode_data.Data()));
+ }
+ printer->Print(
+ " }\n"
+ " return descriptor;\n"
+ "}\n\n");
+
+ printer->Print(
+ "BOOL $name$_IsValidValue(int32_t value__) {\n"
+ " switch (value__) {\n",
+ "name", name_);
+
+ for (int i = 0; i < base_values_.size(); i++) {
+ printer->Print(
+ " case $name$:\n",
+ "name", EnumValueName(base_values_[i]));
+ }
+
+ printer->Print(
+ " return YES;\n"
+ " default:\n"
+ " return NO;\n"
+ " }\n"
+ "}\n\n");
+}
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.h b/src/google/protobuf/compiler/objectivec/objectivec_enum.h
new file mode 100644
index 00000000..0b41cf73
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.h
@@ -0,0 +1,73 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__
+
+#include <string>
+#include <set>
+#include <vector>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+class Printer; // printer.h
+}
+}
+
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class EnumGenerator {
+ public:
+ explicit EnumGenerator(const EnumDescriptor* descriptor);
+ ~EnumGenerator();
+
+ void GenerateHeader(io::Printer* printer);
+ void GenerateSource(io::Printer* printer);
+
+ const string& name() const { return name_; }
+
+ private:
+ const EnumDescriptor* descriptor_;
+ vector<const EnumValueDescriptor*> base_values_;
+ vector<const EnumValueDescriptor*> all_values_;
+ const string name_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
new file mode 100644
index 00000000..30a13ddb
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
@@ -0,0 +1,144 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_enum_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+void SetEnumVariables(const FieldDescriptor* descriptor,
+ map<string, string>* variables) {
+ string type = EnumName(descriptor->enum_type());
+ (*variables)["storage_type"] = type;
+ // For non repeated fields, if it was defined in a different file, the
+ // property decls need to use "enum NAME" rather than just "NAME" to support
+ // the forward declaration of the enums.
+ if (!descriptor->is_repeated() &&
+ (descriptor->file() != descriptor->enum_type()->file())) {
+ (*variables)["property_type"] = "enum " + type;
+ }
+ (*variables)["enum_verifier"] = type + "_IsValidValue";
+ (*variables)["enum_desc_func"] = type + "_EnumDescriptor";
+
+ const Descriptor* msg_descriptor = descriptor->containing_type();
+ (*variables)["owning_message_class"] = ClassName(msg_descriptor);
+}
+} // namespace
+
+EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor)
+ : SingleFieldGenerator(descriptor) {
+ SetEnumVariables(descriptor, &variables_);
+}
+
+EnumFieldGenerator::~EnumFieldGenerator() {}
+
+void EnumFieldGenerator::GenerateFieldDescriptionTypeSpecific(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ " .dataTypeSpecific.enumDescFunc = $enum_desc_func$,\n");
+}
+
+void EnumFieldGenerator::GenerateCFunctionDeclarations(
+ io::Printer* printer) const {
+ if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ return;
+ }
+
+ printer->Print(
+ variables_,
+ "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message);\n"
+ "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value);\n"
+ "\n");
+}
+
+void EnumFieldGenerator::GenerateCFunctionImplementations(
+ io::Printer* printer) const {
+ if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) return;
+
+ printer->Print(
+ variables_,
+ "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message) {\n"
+ " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n"
+ " GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n"
+ " return GPBGetMessageInt32Field(message, field);\n"
+ "}\n"
+ "\n"
+ "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value) {\n"
+ " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n"
+ " GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n"
+ " GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);\n"
+ "}\n"
+ "\n");
+}
+
+void EnumFieldGenerator::DetermineForwardDeclarations(
+ set<string>* fwd_decls) const {
+ // If it is an enum defined in a different file, then we'll need a forward
+ // declaration for it. When it is in our file, all the enums are output
+ // before the message, so it will be declared before it is needed.
+ if (descriptor_->file() != descriptor_->enum_type()->file()) {
+ // Enum name is already in "storage_type".
+ const string& name = variable("storage_type");
+ fwd_decls->insert("GPB_ENUM_FWD_DECLARE(" + name + ")");
+ }
+}
+
+RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
+ const FieldDescriptor* descriptor)
+ : RepeatedFieldGenerator(descriptor) {
+ SetEnumVariables(descriptor, &variables_);
+ variables_["array_storage_type"] = "GPBEnumArray";
+}
+
+RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
+
+void RepeatedEnumFieldGenerator::GenerateFieldDescriptionTypeSpecific(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ " .dataTypeSpecific.enumDescFunc = $enum_desc_func$,\n");
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
new file mode 100644
index 00000000..b629eae8
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
@@ -0,0 +1,78 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class EnumFieldGenerator : public SingleFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ public:
+ virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
+ virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
+ virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
+ virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+
+ protected:
+ explicit EnumFieldGenerator(const FieldDescriptor* descriptor);
+ virtual ~EnumFieldGenerator();
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
+};
+
+class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ public:
+ virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
+
+ protected:
+ RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor);
+ virtual ~RepeatedEnumFieldGenerator();
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
new file mode 100644
index 00000000..4e348393
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
@@ -0,0 +1,136 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <iostream>
+
+#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+ExtensionGenerator::ExtensionGenerator(const string& root_class_name,
+ const FieldDescriptor* descriptor)
+ : method_name_(ExtensionMethodName(descriptor)),
+ root_class_and_method_name_(root_class_name + "_" + method_name_),
+ descriptor_(descriptor) {
+ if (descriptor->is_map()) {
+ // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
+ // error cases, so it seems to be ok to use as a back door for errors.
+ cerr << "error: Extension is a map<>!"
+ << " That used to be blocked by the compiler." << endl;
+ cerr.flush();
+ abort();
+ }
+}
+
+ExtensionGenerator::~ExtensionGenerator() {}
+
+void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) {
+ map<string, string> vars;
+ vars["method_name"] = method_name_;
+ SourceLocation location;
+ if (descriptor_->GetSourceLocation(&location)) {
+ vars["comments"] = BuildCommentsString(location);
+ } else {
+ vars["comments"] = "";
+ }
+ printer->Print(vars,
+ "$comments$"
+ "+ (GPBExtensionDescriptor *)$method_name$;\n");
+}
+
+void ExtensionGenerator::GenerateStaticVariablesInitialization(
+ io::Printer* printer) {
+ map<string, string> vars;
+ vars["root_class_and_method_name"] = root_class_and_method_name_;
+ vars["extended_type"] = ClassName(descriptor_->containing_type());
+ vars["number"] = SimpleItoa(descriptor_->number());
+
+ std::vector<string> options;
+ if (descriptor_->is_repeated()) options.push_back("GPBExtensionRepeated");
+ if (descriptor_->is_packed()) options.push_back("GPBExtensionPacked");
+ if (descriptor_->containing_type()->options().message_set_wire_format())
+ options.push_back("GPBExtensionSetWireFormat");
+
+ vars["options"] = BuildFlagsString(options);
+
+ ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
+ string singular_type;
+ if (objc_type == OBJECTIVECTYPE_MESSAGE) {
+ vars["type"] = string("GPBStringifySymbol(") +
+ ClassName(descriptor_->message_type()) + ")";
+ } else {
+ vars["type"] = "NULL";
+ }
+
+ vars["default_name"] = GPBGenericValueFieldName(descriptor_);
+ if (descriptor_->is_repeated()) {
+ vars["default"] = "nil";
+ } else {
+ vars["default"] = DefaultValue(descriptor_);
+ }
+ string type = GetCapitalizedType(descriptor_);
+ vars["extension_type"] = string("GPBDataType") + type;
+
+ if (objc_type == OBJECTIVECTYPE_ENUM) {
+ vars["enum_desc_func_name"] =
+ EnumName(descriptor_->enum_type()) + "_EnumDescriptor";
+ } else {
+ vars["enum_desc_func_name"] = "NULL";
+ }
+
+ printer->Print(vars,
+ "{\n"
+ " .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"
+ "},\n");
+}
+
+void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) {
+ printer->Print(
+ "[registry addExtension:$root_class_and_method_name$];\n",
+ "root_class_and_method_name", root_class_and_method_name_);
+}
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.h b/src/google/protobuf/compiler/objectivec/objectivec_extension.h
new file mode 100644
index 00000000..e361e639
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.h
@@ -0,0 +1,69 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_EXTENSION_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_EXTENSION_H__
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+class FieldDescriptor; // descriptor.h
+namespace io {
+class Printer; // printer.h
+}
+}
+
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class ExtensionGenerator {
+ public:
+ ExtensionGenerator(const string& root_class_name,
+ const FieldDescriptor* descriptor);
+ ~ExtensionGenerator();
+
+ void GenerateMembersHeader(io::Printer* printer);
+ void GenerateStaticVariablesInitialization(io::Printer* printer);
+ void GenerateRegistrationSource(io::Printer* printer);
+
+ private:
+ string method_name_;
+ string root_class_and_method_name_;
+ const FieldDescriptor* descriptor_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
+};
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
new file mode 100644
index 00000000..cf5d8cfb
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
@@ -0,0 +1,434 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/compiler/objectivec/objectivec_enum_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_map_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_message_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+void SetCommonFieldVariables(const FieldDescriptor* descriptor,
+ map<string, string>* variables) {
+ string camel_case_name = FieldName(descriptor);
+ string raw_field_name;
+ if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
+ raw_field_name = descriptor->message_type()->name();
+ } else {
+ raw_field_name = descriptor->name();
+ }
+ // The logic here has to match -[GGPBFieldDescriptor textFormatName].
+ const string un_camel_case_name(
+ UnCamelCaseFieldName(camel_case_name, descriptor));
+ const bool needs_custom_name = (raw_field_name != un_camel_case_name);
+
+ SourceLocation location;
+ if (descriptor->GetSourceLocation(&location)) {
+ (*variables)["comments"] = BuildCommentsString(location);
+ } else {
+ (*variables)["comments"] = "\n";
+ }
+ const string& classname = ClassName(descriptor->containing_type());
+ (*variables)["classname"] = classname;
+ (*variables)["name"] = camel_case_name;
+ const string& capitalized_name = FieldNameCapitalized(descriptor);
+ (*variables)["capitalized_name"] = capitalized_name;
+ (*variables)["raw_field_name"] = raw_field_name;
+ (*variables)["field_number_name"] =
+ classname + "_FieldNumber_" + capitalized_name;
+ (*variables)["field_number"] = SimpleItoa(descriptor->number());
+ (*variables)["has_index"] = SimpleItoa(descriptor->index());
+ (*variables)["field_type"] = GetCapitalizedType(descriptor);
+ std::vector<string> field_flags;
+ if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated");
+ if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired");
+ if (descriptor->is_optional()) field_flags.push_back("GPBFieldOptional");
+ if (descriptor->is_packed()) field_flags.push_back("GPBFieldPacked");
+
+ // ObjC custom flags.
+ if (descriptor->has_default_value())
+ field_flags.push_back("GPBFieldHasDefaultValue");
+ if (needs_custom_name) field_flags.push_back("GPBFieldTextFormatNameCustom");
+ if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
+ field_flags.push_back("GPBFieldHasEnumDescriptor");
+ }
+
+ (*variables)["fieldflags"] = BuildFlagsString(field_flags);
+
+ (*variables)["default"] = DefaultValue(descriptor);
+ (*variables)["default_name"] = GPBGenericValueFieldName(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"] = "";
+ }
+
+ // Clear some common things so they can be set just when needed.
+ (*variables)["storage_attribute"] = "";
+}
+
+} // namespace
+
+FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) {
+ FieldGenerator* result = NULL;
+ if (field->is_repeated()) {
+ switch (GetObjectiveCType(field)) {
+ case OBJECTIVECTYPE_MESSAGE: {
+ if (field->is_map()) {
+ result = new MapFieldGenerator(field);
+ } else {
+ result = new RepeatedMessageFieldGenerator(field);
+ }
+ break;
+ }
+ case OBJECTIVECTYPE_ENUM:
+ result = new RepeatedEnumFieldGenerator(field);
+ break;
+ default:
+ result = new RepeatedPrimitiveFieldGenerator(field);
+ break;
+ }
+ } else {
+ switch (GetObjectiveCType(field)) {
+ case OBJECTIVECTYPE_MESSAGE: {
+ result = new MessageFieldGenerator(field);
+ break;
+ }
+ case OBJECTIVECTYPE_ENUM:
+ result = new EnumFieldGenerator(field);
+ break;
+ default:
+ if (IsReferenceType(field)) {
+ result = new PrimitiveObjFieldGenerator(field);
+ } else {
+ result = new PrimitiveFieldGenerator(field);
+ }
+ break;
+ }
+ }
+ result->FinishInitialization();
+ return result;
+}
+
+
+FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor)
+ : descriptor_(descriptor) {
+ SetCommonFieldVariables(descriptor, &variables_);
+}
+
+FieldGenerator::~FieldGenerator() {}
+
+void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "$field_number_name$ = $field_number$,\n");
+}
+
+void FieldGenerator::GenerateCFunctionDeclarations(
+ io::Printer* printer) const {
+ // Nothing
+}
+
+void FieldGenerator::GenerateCFunctionImplementations(
+ io::Printer* printer) const {
+ // Nothing
+}
+
+void FieldGenerator::DetermineForwardDeclarations(
+ set<string>* fwd_decls) const {
+ // Nothing
+}
+
+void FieldGenerator::GenerateFieldDescription(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "{\n"
+ " .name = \"$name$\",\n"
+ " .number = $field_number_name$,\n"
+ " .hasIndex = $has_index$,\n"
+ " .flags = $fieldflags$,\n"
+ " .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");
+ } else {
+ // Can't use PrintRaw() here to get the #if/#else/#endif lines completely
+ // outdented because the need for indent captured on the previous
+ // printing of a \n and there is no way to get the current indent level
+ // to call the right number of Outdent()/Indents() to maintain state.
+ printer->Print(
+ variables_,
+ "#if GPBOBJC_INCLUDE_FIELD_OPTIONS\n"
+ " .fieldOptions = $fieldoptions$,\n"
+ "#else\n"
+ " .fieldOptions = NULL,\n"
+ "#endif // GPBOBJC_INCLUDE_FIELD_OPTIONS\n");
+ }
+
+ printer->Print("},\n");
+}
+
+void FieldGenerator::GenerateFieldDescriptionTypeSpecific(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ " .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n");
+}
+
+void FieldGenerator::SetOneofIndexBase(int index_base) {
+ if (descriptor_->containing_oneof() != NULL) {
+ int index = descriptor_->containing_oneof()->index() + index_base;
+ // Flip the sign to mark it as a oneof.
+ variables_["has_index"] = SimpleItoa(-index);
+ }
+}
+
+void FieldGenerator::FinishInitialization(void) {
+ // If "property_type" wasn't set, make it "storage_type".
+ if ((variables_.find("property_type") == variables_.end()) &&
+ (variables_.find("storage_type") != variables_.end())) {
+ variables_["property_type"] = variable("storage_type");
+ }
+}
+
+SingleFieldGenerator::SingleFieldGenerator(
+ const FieldDescriptor* descriptor)
+ : FieldGenerator(descriptor) {
+ // Nothing
+}
+
+SingleFieldGenerator::~SingleFieldGenerator() {}
+
+void SingleFieldGenerator::GenerateFieldStorageDeclaration(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$storage_type$ $name$;\n");
+}
+
+void SingleFieldGenerator::GeneratePropertyDeclaration(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$comments$");
+ if (WantsHasProperty()) {
+ printer->Print(
+ variables_,
+ "@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n");
+ }
+ printer->Print(
+ variables_,
+ "@property(nonatomic, readwrite) $property_type$ $name$;\n"
+ "\n");
+}
+
+void SingleFieldGenerator::GeneratePropertyImplementation(
+ io::Printer* printer) const {
+ if (WantsHasProperty()) {
+ printer->Print(variables_, "@dynamic has$capitalized_name$, $name$;\n");
+ } else {
+ printer->Print(variables_, "@dynamic $name$;\n");
+ }
+}
+
+bool SingleFieldGenerator::WantsHasProperty(void) const {
+ if (descriptor_->containing_oneof() != NULL) {
+ // If in a oneof, it uses the oneofcase instead of a has bit.
+ return false;
+ }
+ if (HasFieldPresence(descriptor_->file())) {
+ // In proto1/proto2, every field has a has_$name$() method.
+ return true;
+ }
+ return false;
+}
+
+ObjCObjFieldGenerator::ObjCObjFieldGenerator(
+ const FieldDescriptor* descriptor)
+ : SingleFieldGenerator(descriptor) {
+ variables_["property_storage_attribute"] = "strong";
+ if (IsRetainedName(variables_["name"])) {
+ variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
+ }
+}
+
+ObjCObjFieldGenerator::~ObjCObjFieldGenerator() {}
+
+void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$storage_type$ *$name$;\n");
+}
+
+void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
+ io::Printer* printer) const {
+
+ // Differs from SingleFieldGenerator::GeneratePropertyDeclaration() in that
+ // it uses pointers and deals with Objective C's rules around storage name
+ // conventions (init*, new*, etc.)
+
+ printer->Print(variables_, "$comments$");
+ if (WantsHasProperty()) {
+ printer->Print(
+ variables_,
+ "@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n");
+ }
+ printer->Print(
+ variables_,
+ "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$;\n");
+ if (IsInitName(variables_.find("name")->second)) {
+ // If property name starts with init we need to annotate it to get past ARC.
+ // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
+ printer->Print(variables_,
+ "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n");
+ }
+ printer->Print("\n");
+}
+
+RepeatedFieldGenerator::RepeatedFieldGenerator(
+ const FieldDescriptor* descriptor)
+ : ObjCObjFieldGenerator(descriptor) {
+ // Repeated fields don't use the has index.
+ variables_["has_index"] = "GPBNoHasBit";
+}
+
+RepeatedFieldGenerator::~RepeatedFieldGenerator() {}
+
+void RepeatedFieldGenerator::FinishInitialization(void) {
+ FieldGenerator::FinishInitialization();
+ variables_["array_comment"] =
+ "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n";
+}
+
+void RepeatedFieldGenerator::GenerateFieldStorageDeclaration(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$array_storage_type$ *$name$;\n");
+}
+
+void RepeatedFieldGenerator::GeneratePropertyImplementation(
+ io::Printer* printer) const {
+ printer->Print(variables_, "@dynamic $name$, $name$_Count;\n");
+}
+
+void RepeatedFieldGenerator::GeneratePropertyDeclaration(
+ io::Printer* printer) const {
+
+ // Repeated fields don't need the has* properties, but they do expose a
+ // *Count (to check without autocreation). So for the field property we need
+ // the same logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for
+ // dealing with needing Objective C's rules around storage name conventions
+ // (init*, new*, etc.)
+
+ printer->Print(
+ variables_,
+ "$comments$"
+ "$array_comment$"
+ "@property(nonatomic, readwrite, strong, null_resettable) $array_storage_type$ *$name$$storage_attribute$;\n"
+ "@property(nonatomic, readonly) NSUInteger $name$_Count;\n");
+ if (IsInitName(variables_.find("name")->second)) {
+ // If property name starts with init we need to annotate it to get past ARC.
+ // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
+ printer->Print(variables_,
+ "- ($array_storage_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n");
+ }
+ printer->Print("\n");
+}
+
+bool RepeatedFieldGenerator::WantsHasProperty(void) const {
+ // Consumer check the array size/existance rather than a has bit.
+ return false;
+}
+
+FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
+ : descriptor_(descriptor),
+ field_generators_(
+ new scoped_ptr<FieldGenerator>[descriptor->field_count()]),
+ extension_generators_(
+ new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
+ // Construct all the FieldGenerators.
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ field_generators_[i].reset(FieldGenerator::Make(descriptor->field(i)));
+ }
+ for (int i = 0; i < descriptor->extension_count(); i++) {
+ extension_generators_[i].reset(FieldGenerator::Make(descriptor->extension(i)));
+ }
+}
+
+FieldGeneratorMap::~FieldGeneratorMap() {}
+
+const FieldGenerator& FieldGeneratorMap::get(
+ const FieldDescriptor* field) const {
+ GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
+ return *field_generators_[field->index()];
+}
+
+const FieldGenerator& FieldGeneratorMap::get_extension(int index) const {
+ return *extension_generators_[index];
+}
+
+void FieldGeneratorMap::SetOneofIndexBase(int index_base) {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_[i]->SetOneofIndexBase(index_base);
+ }
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/google/protobuf/compiler/objectivec/objectivec_field.h
new file mode 100644
index 00000000..130a52dd
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.h
@@ -0,0 +1,168 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+
+namespace io {
+class Printer; // printer.h
+} // namespace io
+
+namespace compiler {
+namespace objectivec {
+
+class FieldGenerator {
+ public:
+ static FieldGenerator* Make(const FieldDescriptor* field);
+
+ virtual ~FieldGenerator();
+
+ virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const = 0;
+ virtual void GeneratePropertyDeclaration(io::Printer* printer) const = 0;
+
+ virtual void GeneratePropertyImplementation(io::Printer* printer) const = 0;
+
+ virtual void GenerateFieldDescription(io::Printer* printer) const;
+ virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
+ virtual void GenerateFieldNumberConstant(io::Printer* printer) const;
+
+ virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
+ virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
+
+ virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+
+ void SetOneofIndexBase(int index_base);
+
+ string variable(const char* key) const {
+ return variables_.find(key)->second;
+ }
+
+ bool needs_textformat_name_support() const {
+ const string& field_flags = variable("fieldflags");
+ return field_flags.find("GPBFieldTextFormatNameCustom") != string::npos;
+ }
+ string generated_objc_name() const { return variable("name"); }
+ string raw_field_name() const { return variable("raw_field_name"); }
+
+ protected:
+ explicit FieldGenerator(const FieldDescriptor* descriptor);
+
+ virtual void FinishInitialization(void);
+ virtual bool WantsHasProperty(void) const = 0;
+
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
+};
+
+class SingleFieldGenerator : public FieldGenerator {
+ public:
+ virtual ~SingleFieldGenerator();
+
+ virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const;
+ virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
+
+ virtual void GeneratePropertyImplementation(io::Printer* printer) const;
+
+ protected:
+ explicit SingleFieldGenerator(const FieldDescriptor* descriptor);
+ virtual bool WantsHasProperty(void) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingleFieldGenerator);
+};
+
+// Subclass with common support for when the field ends up as an ObjC Object.
+class ObjCObjFieldGenerator : public SingleFieldGenerator {
+ public:
+ virtual ~ObjCObjFieldGenerator();
+
+ virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const;
+ virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
+
+ protected:
+ explicit ObjCObjFieldGenerator(const FieldDescriptor* descriptor);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjCObjFieldGenerator);
+};
+
+class RepeatedFieldGenerator : public ObjCObjFieldGenerator {
+ public:
+ virtual ~RepeatedFieldGenerator();
+
+ virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const;
+ virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
+
+ virtual void GeneratePropertyImplementation(io::Printer* printer) const;
+
+ protected:
+ explicit RepeatedFieldGenerator(const FieldDescriptor* descriptor);
+ virtual void FinishInitialization(void);
+ virtual bool WantsHasProperty(void) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedFieldGenerator);
+};
+
+// Convenience class which constructs FieldGenerators for a Descriptor.
+class FieldGeneratorMap {
+ public:
+ explicit FieldGeneratorMap(const Descriptor* descriptor);
+ ~FieldGeneratorMap();
+
+ const FieldGenerator& get(const FieldDescriptor* field) const;
+ const FieldGenerator& get_extension(int index) const;
+
+ void SetOneofIndexBase(int index_base);
+
+ private:
+ const Descriptor* descriptor_;
+ scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
+ scoped_array<scoped_ptr<FieldGenerator> > extension_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
+};
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
new file mode 100644
index 00000000..e60ae5a6
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
@@ -0,0 +1,371 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/objectivec/objectivec_file.h>
+#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
+#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
+#include <google/protobuf/compiler/objectivec/objectivec_message.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/stl_util.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <sstream>
+
+namespace google {
+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;
+
+namespace compiler {
+namespace objectivec {
+
+FileGenerator::FileGenerator(const FileDescriptor *file)
+ : file_(file),
+ root_class_name_(FileClassName(file)),
+ is_public_dep_(false) {
+ // Validate the objc prefix.
+ ValidateObjCClassPrefix(file_);
+
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ EnumGenerator *generator = new EnumGenerator(file_->enum_type(i));
+ enum_generators_.push_back(generator);
+ }
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ MessageGenerator *generator =
+ new MessageGenerator(root_class_name_, file_->message_type(i));
+ message_generators_.push_back(generator);
+ }
+ for (int i = 0; i < file_->extension_count(); i++) {
+ ExtensionGenerator *generator =
+ new ExtensionGenerator(root_class_name_, file_->extension(i));
+ extension_generators_.push_back(generator);
+ }
+}
+
+FileGenerator::~FileGenerator() {
+ STLDeleteContainerPointers(dependency_generators_.begin(),
+ dependency_generators_.end());
+ STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end());
+ STLDeleteContainerPointers(message_generators_.begin(),
+ message_generators_.end());
+ STLDeleteContainerPointers(extension_generators_.begin(),
+ extension_generators_.end());
+}
+
+void FileGenerator::GenerateHeader(io::Printer *printer) {
+ printer->Print(
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
+ "\n",
+ "filename", file_->name());
+
+ printer->Print(
+ "#import \"GPBProtocolBuffers.h\"\n"
+ "\n");
+
+ // Add some verification that the generated code matches the source the
+ // code is being compiled with.
+ printer->Print(
+ "#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != $protoc_gen_objc_version$\n"
+ "#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources.\n"
+ "#endif\n"
+ "\n",
+ "protoc_gen_objc_version",
+ SimpleItoa(GOOGLE_PROTOBUF_OBJC_GEN_VERSION));
+
+ const vector<FileGenerator *> &dependency_generators = DependencyGenerators();
+ for (vector<FileGenerator *>::const_iterator iter =
+ dependency_generators.begin();
+ iter != dependency_generators.end(); ++iter) {
+ if ((*iter)->IsPublicDependency()) {
+ printer->Print("#import \"$header$.pbobjc.h\"\n",
+ "header", (*iter)->Path());
+ }
+ }
+
+ printer->Print(
+ "// @@protoc_insertion_point(imports)\n"
+ "\n"
+ "CF_EXTERN_C_BEGIN\n"
+ "\n");
+
+ set<string> fwd_decls;
+ for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+ iter != message_generators_.end(); ++iter) {
+ (*iter)->DetermineForwardDeclarations(&fwd_decls);
+ }
+ for (set<string>::const_iterator i(fwd_decls.begin());
+ i != fwd_decls.end(); ++i) {
+ printer->Print("$value$;\n", "value", *i);
+ }
+ if (fwd_decls.begin() != fwd_decls.end()) {
+ printer->Print("\n");
+ }
+
+ printer->Print(
+ "NS_ASSUME_NONNULL_BEGIN\n"
+ "\n");
+
+ // need to write out all enums first
+ for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin();
+ iter != enum_generators_.end(); ++iter) {
+ (*iter)->GenerateHeader(printer);
+ }
+
+ for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+ iter != message_generators_.end(); ++iter) {
+ (*iter)->GenerateEnumHeader(printer);
+ }
+
+ // For extensions to chain together, the Root gets created even if there
+ // are no extensions.
+ printer->Print(
+ "#pragma mark - $root_class_name$\n"
+ "\n"
+ "@interface $root_class_name$ : GPBRootObject\n"
+ "\n"
+ "// The base class provides:\n"
+ "// + (GPBExtensionRegistry *)extensionRegistry;\n"
+ "// which is an GPBExtensionRegistry that includes all the extensions defined by\n"
+ "// this file and all files that it depends on.\n"
+ "\n"
+ "@end\n"
+ "\n",
+ "root_class_name", root_class_name_);
+
+ if (extension_generators_.size() > 0) {
+ // The dynamic methods block is only needed if there are extensions.
+ printer->Print(
+ "@interface $root_class_name$ (DynamicMethods)\n",
+ "root_class_name", root_class_name_);
+
+ for (vector<ExtensionGenerator *>::iterator iter =
+ extension_generators_.begin();
+ iter != extension_generators_.end(); ++iter) {
+ (*iter)->GenerateMembersHeader(printer);
+ }
+
+ printer->Print("@end\n\n");
+ } // extension_generators_.size() > 0
+
+ for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+ iter != message_generators_.end(); ++iter) {
+ (*iter)->GenerateMessageHeader(printer);
+ }
+
+ printer->Print(
+ "NS_ASSUME_NONNULL_END\n"
+ "\n"
+ "CF_EXTERN_C_END\n"
+ "\n"
+ "// @@protoc_insertion_point(global_scope)\n");
+}
+
+void FileGenerator::GenerateSource(io::Printer *printer) {
+ printer->Print(
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
+ "\n",
+ "filename", file_->name());
+
+ string header_file = Path() + ".pbobjc.h";
+ printer->Print(
+ "#import \"GPBProtocolBuffers_RuntimeSupport.h\"\n"
+ "#import \"$header_file$\"\n",
+ "header_file", header_file);
+ const vector<FileGenerator *> &dependency_generators =
+ DependencyGenerators();
+ for (vector<FileGenerator *>::const_iterator iter =
+ dependency_generators.begin();
+ iter != dependency_generators.end(); ++iter) {
+ if (!(*iter)->IsPublicDependency()) {
+ printer->Print("#import \"$header$.pbobjc.h\"\n",
+ "header", (*iter)->Path());
+ }
+ }
+ printer->Print(
+ "// @@protoc_insertion_point(imports)\n"
+ "\n");
+
+ printer->Print(
+ "#pragma mark - $root_class_name$\n"
+ "\n"
+ "@implementation $root_class_name$\n\n",
+ "root_class_name", root_class_name_);
+
+ // Generate the extension initialization structures for the top level and
+ // any nested messages.
+ ostringstream extensions_stringstream;
+ if (file_->extension_count() + file_->message_type_count() > 0) {
+ io::OstreamOutputStream extensions_outputstream(&extensions_stringstream);
+ io::Printer extensions_printer(&extensions_outputstream, '$');
+ for (vector<ExtensionGenerator *>::iterator iter =
+ extension_generators_.begin();
+ iter != extension_generators_.end(); ++iter) {
+ (*iter)->GenerateStaticVariablesInitialization(&extensions_printer);
+ }
+ for (vector<MessageGenerator *>::iterator iter =
+ message_generators_.begin();
+ iter != message_generators_.end(); ++iter) {
+ (*iter)->GenerateStaticVariablesInitialization(&extensions_printer);
+ }
+ extensions_stringstream.flush();
+ }
+
+ // If there were any extensions or this file has any dependencies, output
+ // a registry to override to create the file specific registry.
+ const string& extensions_str = extensions_stringstream.str();
+ if (extensions_str.length() > 0 || file_->dependency_count() > 0) {
+ printer->Print(
+ "+ (GPBExtensionRegistry*)extensionRegistry {\n"
+ " // This is called by +initialize so there is no need to worry\n"
+ " // about thread safety and initialization of registry.\n"
+ " static GPBExtensionRegistry* registry = nil;\n"
+ " if (!registry) {\n"
+ " GPBDebugCheckRuntimeVersion();\n"
+ " registry = [[GPBExtensionRegistry alloc] init];\n");
+
+ printer->Indent();
+ printer->Indent();
+
+ if (extensions_str.length() > 0) {
+ printer->Print(
+ "static GPBExtensionDescription descriptions[] = {\n");
+ printer->Indent();
+ printer->Print(extensions_str.c_str());
+ printer->Outdent();
+ printer->Print(
+ "};\n"
+ "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n"
+ " GPBExtensionDescriptor *extension =\n"
+ " [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]];\n"
+ " [registry addExtension:extension];\n"
+ " [self globallyRegisterExtension:extension];\n"
+ " [extension release];\n"
+ "}\n");
+ }
+
+ const vector<FileGenerator *> &dependency_generators =
+ DependencyGenerators();
+ for (vector<FileGenerator *>::const_iterator iter =
+ dependency_generators.begin();
+ iter != dependency_generators.end(); ++iter) {
+ printer->Print(
+ "[registry addExtensions:[$dependency$ extensionRegistry]];\n",
+ "dependency", (*iter)->RootClassName());
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+
+ printer->Print(
+ " }\n"
+ " return registry;\n"
+ "}\n"
+ "\n");
+ }
+
+ printer->Print("@end\n\n");
+
+ // File descriptor only needed if there are messages to use it.
+ if (message_generators_.size() > 0) {
+ string syntax;
+ switch (file_->syntax()) {
+ case FileDescriptor::SYNTAX_UNKNOWN:
+ syntax = "GPBFileSyntaxUnknown";
+ break;
+ case FileDescriptor::SYNTAX_PROTO2:
+ syntax = "GPBFileSyntaxProto2";
+ break;
+ case FileDescriptor::SYNTAX_PROTO3:
+ syntax = "GPBFileSyntaxProto3";
+ break;
+ }
+ printer->Print(
+ "#pragma mark - $root_class_name$_FileDescriptor\n"
+ "\n"
+ "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n"
+ " // This is called by +initialize so there is no need to worry\n"
+ " // about thread safety of the singleton.\n"
+ " static GPBFileDescriptor *descriptor = NULL;\n"
+ " if (!descriptor) {\n"
+ " GPBDebugCheckRuntimeVersion();\n"
+ " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
+ " syntax:$syntax$];\n"
+ " }\n"
+ " return descriptor;\n"
+ "}\n"
+ "\n",
+ "root_class_name", root_class_name_,
+ "package", file_->package(),
+ "syntax", syntax);
+ }
+
+ for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin();
+ iter != enum_generators_.end(); ++iter) {
+ (*iter)->GenerateSource(printer);
+ }
+ for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+ iter != message_generators_.end(); ++iter) {
+ (*iter)->GenerateSource(printer);
+ }
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(global_scope)\n");
+}
+
+const string FileGenerator::Path() const { return FilePath(file_); }
+
+const vector<FileGenerator *> &FileGenerator::DependencyGenerators() {
+ if (file_->dependency_count() != dependency_generators_.size()) {
+ set<string> public_import_names;
+ for (int i = 0; i < file_->public_dependency_count(); i++) {
+ public_import_names.insert(file_->public_dependency(i)->name());
+ }
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ FileGenerator *generator = new FileGenerator(file_->dependency(i));
+ const string& name = file_->dependency(i)->name();
+ bool public_import = (public_import_names.count(name) != 0);
+ generator->SetIsPublicDependency(public_import);
+ dependency_generators_.push_back(generator);
+ }
+ }
+ return dependency_generators_;
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h
new file mode 100644
index 00000000..1bb4f0ea
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h
@@ -0,0 +1,97 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
+
+#include <string>
+#include <set>
+#include <vector>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+class FileDescriptor; // descriptor.h
+namespace io {
+class Printer; // printer.h
+}
+}
+
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class EnumGenerator;
+class ExtensionGenerator;
+class MessageGenerator;
+
+class FileGenerator {
+ public:
+ explicit FileGenerator(const FileDescriptor* file);
+ ~FileGenerator();
+
+ void GenerateSource(io::Printer* printer);
+ void GenerateHeader(io::Printer* printer);
+
+ const string& RootClassName() const { return root_class_name_; }
+ const string Path() const;
+
+ bool IsPublicDependency() const { return is_public_dep_; }
+
+ protected:
+ void SetIsPublicDependency(bool is_public_dep) {
+ is_public_dep_ = is_public_dep;
+ }
+
+ private:
+ const FileDescriptor* file_;
+ string root_class_name_;
+
+ // Access this field through the DependencyGenerators accessor call below.
+ // Do not reference it directly.
+ vector<FileGenerator*> dependency_generators_;
+
+ vector<EnumGenerator*> enum_generators_;
+ vector<MessageGenerator*> message_generators_;
+ vector<ExtensionGenerator*> extension_generators_;
+ bool is_public_dep_;
+
+ const vector<FileGenerator*>& DependencyGenerators();
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
new file mode 100644
index 00000000..4449087a
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
@@ -0,0 +1,86 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <iostream>
+#include <google/protobuf/compiler/objectivec/objectivec_generator.h>
+#include <google/protobuf/compiler/objectivec/objectivec_file.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+ObjectiveCGenerator::ObjectiveCGenerator() {}
+
+ObjectiveCGenerator::~ObjectiveCGenerator() {}
+
+bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
+ const string& parameter,
+ OutputDirectory* output_directory,
+ string* error) const {
+ // ObjC doesn't have any options at the moment, error if passed one.
+ vector<pair<string, string> > options;
+ ParseGeneratorParameter(parameter, &options);
+ for (int i = 0; i < options.size(); i++) {
+ *error = "error:: Unknown generator option: " + options[i].first;
+ return false;
+ }
+
+ FileGenerator file_generator(file);
+
+ string filepath = FilePath(file);
+
+ // Generate header.
+ {
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ output_directory->Open(filepath + ".pbobjc.h"));
+ io::Printer printer(output.get(), '$');
+ file_generator.GenerateHeader(&printer);
+ }
+
+ // Generate m file.
+ {
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ output_directory->Open(filepath + ".pbobjc.m"));
+ io::Printer printer(output.get(), '$');
+ file_generator.GenerateSource(&printer);
+ }
+
+ return true;
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/google/protobuf/compiler/objectivec/objectivec_generator.h
new file mode 100644
index 00000000..24286ac9
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.h
@@ -0,0 +1,60 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Generates ObjectiveC code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__
+
+#include <string>
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class LIBPROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator {
+ public:
+ ObjectiveCGenerator();
+ ~ObjectiveCGenerator();
+
+ // implements CodeGenerator ----------------------------------------
+ bool Generate(const FileDescriptor* file, const string& parameter,
+ OutputDirectory* output_directory, string* error) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectiveCGenerator);
+};
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
new file mode 100644
index 00000000..45d122d1
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
@@ -0,0 +1,1045 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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 <climits>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
+// error cases, so it seems to be ok to use as a back door for errors.
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+// islower()/isupper()/tolower()/toupper() change based on locale.
+//
+// src/google/protobuf/stubs/strutil.h:150 has the same pattern. For the
+// Objective C plugin, test failures were seen on TravisCI because isupper('A')
+// was coming back false for some server's locale. This approach avoids any
+// such issues.
+
+bool IsLower(const char c) {
+ return ('a' <= c && c <= 'z');
+}
+
+bool IsUpper(const char c) {
+ return ('A' <= c && c <= 'Z');
+}
+
+char ToLower(char c) {
+ if ('A' <= c && c <= 'Z') {
+ c += 'a' - 'A';
+ }
+ return c;
+}
+
+// toupper() changes based on locale. We don't want this!
+char ToUpper(char c) {
+ if ('a' <= c && c <= 'z') {
+ c += 'A' - 'a';
+ }
+ return c;
+}
+
+string TrimString(const string& s) {
+ string::size_type start = s.find_first_not_of(" \n\r\t");
+ if (start == string::npos) {
+ return "";
+ }
+ string::size_type end = s.find_last_not_of(" \n\r\t") + 1;
+ return s.substr(start, end - start);
+}
+
+hash_set<string> MakeWordsMap(const char* const words[], size_t num_words) {
+ hash_set<string> result;
+ for (int i = 0; i < num_words; i++) {
+ result.insert(words[i]);
+ }
+ return result;
+}
+
+const char* const kUpperSegmentsList[] = {"url", "http", "https"};
+
+hash_set<string> kUpperSegments =
+ MakeWordsMap(kUpperSegmentsList, GOOGLE_ARRAYSIZE(kUpperSegmentsList));
+
+// Internal helper for name handing.
+// Do not expose this outside of helpers, stick to having functions for specific
+// cases (ClassName(), FieldName()), so there is always consistent suffix rules.
+string UnderscoresToCamelCase(const string& input, bool first_capitalized) {
+ vector<string> values;
+ string current;
+
+ bool last_char_was_number = false;
+ bool last_char_was_lower = false;
+ bool last_char_was_upper = false;
+ for (int i = 0; i < input.size(); i++) {
+ char c = input[i];
+ if (c >= '0' && c <= '9') {
+ if (!last_char_was_number) {
+ values.push_back(current);
+ current = "";
+ }
+ current += c;
+ last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+ last_char_was_number = true;
+ } else if (IsLower(c)) {
+ // lowercase letter can follow a lowercase or uppercase letter
+ if (!last_char_was_lower && !last_char_was_upper) {
+ values.push_back(current);
+ current = "";
+ }
+ current += c; // already lower
+ last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+ last_char_was_lower = true;
+ } else if (IsUpper(c)) {
+ if (!last_char_was_upper) {
+ values.push_back(current);
+ current = "";
+ }
+ current += ToLower(c);
+ last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+ last_char_was_upper = true;
+ } else {
+ last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+ }
+ }
+ values.push_back(current);
+
+ for (vector<string>::iterator i = values.begin(); i != values.end(); ++i) {
+ string value = *i;
+ bool all_upper = (kUpperSegments.count(value) > 0);
+ for (int j = 0; j < value.length(); j++) {
+ if (j == 0 || all_upper) {
+ value[j] = ToUpper(value[j]);
+ } else {
+ // Nothing, already in lower.
+ }
+ }
+ *i = value;
+ }
+ string result;
+ for (vector<string>::iterator i = values.begin(); i != values.end(); ++i) {
+ result += *i;
+ }
+ if ((result.length() != 0) && !first_capitalized) {
+ result[0] = ToLower(result[0]);
+ }
+ return result;
+}
+
+const char* const kReservedWordList[] = {
+ // Objective C "keywords" that aren't in C
+ // From
+ // http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c
+ "id", "_cmd", "super", "in", "out", "inout", "bycopy", "byref", "oneway",
+ "self",
+
+ // C/C++ keywords (Incl C++ 0x11)
+ // From http://en.cppreference.com/w/cpp/keywords
+ "and", "and_eq", "alignas", "alignof", "asm", "auto", "bitand", "bitor",
+ "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class",
+ "compl", "const", "constexpr", "const_cast", "continue", "decltype",
+ "default", "delete", "double", "dynamic_cast", "else", "enum", "explicit",
+ "export", "extern ", "false", "float", "for", "friend", "goto", "if",
+ "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not",
+ "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected",
+ "public", "register", "reinterpret_cast", "return", "short", "signed",
+ "sizeof", "static", "static_assert", "static_cast", "struct", "switch",
+ "template", "this", "thread_local", "throw", "true", "try", "typedef",
+ "typeid", "typename", "union", "unsigned", "using", "virtual", "void",
+ "volatile", "wchar_t", "while", "xor", "xor_eq",
+
+ // C99 keywords
+ // From
+ // http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm
+ "restrict",
+
+ // Objective-C Runtime typedefs
+ // From <obc/runtime.h>
+ "Category", "Ivar", "Method", "Protocol",
+
+ // NSObject Methods
+ // new is covered by C++ keywords.
+ "description", "debugDescription", "finalize", "hash", "dealloc", "init",
+ "class", "superclass", "retain", "release", "autorelease", "retainCount",
+ "zone", "isProxy", "copy", "mutableCopy", "classForCoder",
+
+ // GPBMessage Methods
+ // Only need to add instance methods that may conflict with
+ // method declared in protos. The main cases are methods
+ // that take no arguments, or setFoo:/hasFoo: type methods.
+ "clear", "data", "delimitedData", "descriptor", "extensionRegistry",
+ "extensionsCurrentlySet", "isInitialized", "serializedSize",
+ "sortedExtensionsInUse", "unknownFields",
+
+ // MacTypes.h names
+ "Fixed", "Fract", "Size", "LogicalAddress", "PhysicalAddress", "ByteCount",
+ "ByteOffset", "Duration", "AbsoluteTime", "OptionBits", "ItemCount",
+ "PBVersion", "ScriptCode", "LangCode", "RegionCode", "OSType",
+ "ProcessSerialNumber", "Point", "Rect", "FixedPoint", "FixedRect", "Style",
+ "StyleParameter", "StyleField", "TimeScale", "TimeBase", "TimeRecord",
+};
+
+hash_set<string> kReservedWords =
+ MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList));
+
+string SanitizeNameForObjC(const string& input, const string& extension) {
+ if (kReservedWords.count(input) > 0) {
+ return input + extension;
+ }
+ return input;
+}
+
+string NameFromFieldDescriptor(const FieldDescriptor* field) {
+ if (field->type() == FieldDescriptor::TYPE_GROUP) {
+ return field->message_type()->name();
+ } else {
+ return field->name();
+ }
+}
+
+// Escape C++ trigraphs by escaping question marks to \?
+string EscapeTrigraphs(const string& to_escape) {
+ return StringReplace(to_escape, "?", "\\?", true);
+}
+
+void PathSplit(const string& path, string* directory, string* basename) {
+ string::size_type last_slash = path.rfind('/');
+ if (last_slash == string::npos) {
+ if (directory) {
+ *directory = "";
+ }
+ if (basename) {
+ *basename = path;
+ }
+ } else {
+ if (directory) {
+ *directory = path.substr(0, last_slash);
+ }
+ if (basename) {
+ *basename = path.substr(last_slash + 1);
+ }
+ }
+}
+
+bool IsSpecialName(const string& name, const string* special_names,
+ size_t count) {
+ for (size_t i = 0; i < count; ++i) {
+ size_t length = special_names[i].length();
+ if (name.compare(0, length, special_names[i]) == 0) {
+ if (name.length() > length) {
+ // If name is longer than the retained_name[i] that it matches
+ // the next character must be not lower case (newton vs newTon vs
+ // new_ton).
+ return !IsLower(name[length]);
+ } else {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+string StripProto(const string& filename) {
+ if (HasSuffixString(filename, ".protodevel")) {
+ return StripSuffixString(filename, ".protodevel");
+ } else {
+ return StripSuffixString(filename, ".proto");
+ }
+}
+
+bool IsRetainedName(const string& name) {
+ // List of prefixes from
+ // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
+ static const string retained_names[] = {"new", "alloc", "copy",
+ "mutableCopy"};
+ return IsSpecialName(name, retained_names,
+ sizeof(retained_names) / sizeof(retained_names[0]));
+}
+
+bool IsInitName(const string& name) {
+ static const string init_names[] = {"init"};
+ return IsSpecialName(name, init_names,
+ sizeof(init_names) / sizeof(init_names[0]));
+}
+
+string BaseFileName(const FileDescriptor* file) {
+ string basename;
+ PathSplit(file->name(), NULL, &basename);
+ return basename;
+}
+
+string FileName(const FileDescriptor* file) {
+ string path = FilePath(file);
+ string basename;
+ PathSplit(path, NULL, &basename);
+ return basename;
+}
+
+string FilePath(const FileDescriptor* file) {
+ string output;
+ string basename;
+ string directory;
+ PathSplit(file->name(), &directory, &basename);
+ if (directory.length() > 0) {
+ output = directory + "/";
+ }
+ basename = StripProto(basename);
+
+ // CamelCase to be more ObjC friendly.
+ basename = UnderscoresToCamelCase(basename, true);
+
+ output += basename;
+ return output;
+}
+
+string FileClassPrefix(const FileDescriptor* file) {
+ // Default is empty string, no need to check has_objc_class_prefix.
+ string result = file->options().objc_class_prefix();
+ return result;
+}
+
+void ValidateObjCClassPrefix(const FileDescriptor* file) {
+ string prefix = file->options().objc_class_prefix();
+ if (prefix.length() > 0) {
+ // 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.
+ if (!IsUpper(prefix[0])) {
+ cerr << endl
+ << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
+ << prefix << "\";' in '" << file->name() << "';"
+ << " it should start with a capital letter."
+ << endl;
+ cerr.flush();
+ }
+ if (prefix.length() < 3) {
+ cerr << endl
+ << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
+ << prefix << "\";' in '" << file->name() << "';"
+ << " Apple recommends they should be at least 3 characters long."
+ << endl;
+ cerr.flush();
+ }
+ }
+}
+
+string FileClassName(const FileDescriptor* file) {
+ string name = FileClassPrefix(file);
+ name += UnderscoresToCamelCase(StripProto(BaseFileName(file)), true);
+ name += "Root";
+ // There aren't really any reserved words that end in "Root", but playing
+ // it safe and checking.
+ return SanitizeNameForObjC(name, "_RootClass");
+}
+
+string ClassNameWorker(const Descriptor* descriptor) {
+ string name;
+ if (descriptor->containing_type() != NULL) {
+ name = ClassNameWorker(descriptor->containing_type());
+ name += "_";
+ }
+ return name + descriptor->name();
+}
+
+string ClassNameWorker(const EnumDescriptor* descriptor) {
+ string name;
+ if (descriptor->containing_type() != NULL) {
+ name = ClassNameWorker(descriptor->containing_type());
+ name += "_";
+ }
+ return name + descriptor->name();
+}
+
+string ClassName(const Descriptor* descriptor) {
+ // 1. Message names are used as is (style calls for CamelCase, trust it).
+ // 2. Check for reserved word at the very end and then suffix things.
+ string prefix = FileClassPrefix(descriptor->file());
+ string name = ClassNameWorker(descriptor);
+ return SanitizeNameForObjC(prefix + name, "_Class");
+}
+
+string EnumName(const EnumDescriptor* descriptor) {
+ // 1. Enum names are used as is (style calls for CamelCase, trust it).
+ // 2. Check for reserved word at the every end and then suffix things.
+ // message Fixed {
+ // message Size {...}
+ // enum Mumble {...}
+ // ...
+ // }
+ // yields Fixed_Class, Fixed_Size.
+ string name = FileClassPrefix(descriptor->file());
+ name += ClassNameWorker(descriptor);
+ return SanitizeNameForObjC(name, "_Enum");
+}
+
+string EnumValueName(const EnumValueDescriptor* descriptor) {
+ // Because of the Switch enum compatibility, the name on the enum has to have
+ // the suffix handing, so it slightly diverges from how nested classes work.
+ // enum Fixed {
+ // FOO = 1
+ // }
+ // yields Fixed_Enum and Fixed_Enum_Foo (not Fixed_Foo).
+ const string& class_name = EnumName(descriptor->type());
+ const string& value_str = UnderscoresToCamelCase(descriptor->name(), true);
+ const string& name = class_name + "_" + value_str;
+ // There aren't really any reserved words with an underscore and a leading
+ // capital letter, but playing it safe and checking.
+ return SanitizeNameForObjC(name, "_Value");
+}
+
+string EnumValueShortName(const EnumValueDescriptor* descriptor) {
+ // Enum value names (EnumValueName above) are the enum name turned into
+ // a class name and then the value name is CamelCased and concatenated; the
+ // whole thing then gets sanitized for reserved words.
+ // The "short name" is intended to be the final leaf, the value name; but
+ // you can't simply send that off to sanitize as that could result in it
+ // getting modified when the full name didn't. For example enum
+ // "StorageModes" has a value "retain". So the full name is
+ // "StorageModes_Retain", but if we sanitize "retain" it would become
+ // "RetainValue".
+ // So the right way to get the short name is to take the full enum name
+ // and then strip off the enum name (leaving the value name and anything
+ // done by sanitize).
+ const string& class_name = EnumName(descriptor->type());
+ const string& long_name_prefix = class_name + "_";
+ const string& long_name = EnumValueName(descriptor);
+ return StripPrefixString(long_name, long_name_prefix);
+}
+
+string UnCamelCaseEnumShortName(const string& name) {
+ string result;
+ for (int i = 0; i < name.size(); i++) {
+ char c = name[i];
+ if (i > 0 && c >= 'A' && c <= 'Z') {
+ result += '_';
+ }
+ result += ToUpper(c);
+ }
+ return result;
+}
+
+string ExtensionMethodName(const FieldDescriptor* descriptor) {
+ const string& name = NameFromFieldDescriptor(descriptor);
+ const string& result = UnderscoresToCamelCase(name, false);
+ return SanitizeNameForObjC(result, "_Extension");
+}
+
+string FieldName(const FieldDescriptor* field) {
+ const string& name = NameFromFieldDescriptor(field);
+ string result = UnderscoresToCamelCase(name, false);
+ if (field->is_repeated() && !field->is_map()) {
+ // Add "Array" before do check for reserved worlds.
+ result += "Array";
+ } else {
+ // If it wasn't repeated, but ends in "Array", force on the _p suffix.
+ if (HasSuffixString(result, "Array")) {
+ result += "_p";
+ }
+ }
+ return SanitizeNameForObjC(result, "_p");
+}
+
+string FieldNameCapitalized(const FieldDescriptor* field) {
+ // Want the same suffix handling, so upcase the first letter of the other
+ // name.
+ string result = FieldName(field);
+ if (result.length() > 0) {
+ result[0] = ToUpper(result[0]);
+ }
+ return result;
+}
+
+string OneofEnumName(const OneofDescriptor* descriptor) {
+ const Descriptor* fieldDescriptor = descriptor->containing_type();
+ string name = ClassName(fieldDescriptor);
+ name += "_" + UnderscoresToCamelCase(descriptor->name(), true) + "_OneOfCase";
+ // No sanitize needed because the OS never has names that end in _OneOfCase.
+ return name;
+}
+
+string OneofName(const OneofDescriptor* descriptor) {
+ string name = UnderscoresToCamelCase(descriptor->name(), false);
+ // No sanitize needed because it gets OneOfCase added and that shouldn't
+ // ever conflict.
+ return name;
+}
+
+string OneofNameCapitalized(const OneofDescriptor* descriptor) {
+ // Use the common handling and then up-case the first letter.
+ string result = OneofName(descriptor);
+ if (result.length() > 0) {
+ result[0] = ToUpper(result[0]);
+ }
+ return result;
+}
+
+string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field) {
+ string worker(name);
+ if (HasSuffixString(worker, "_p")) {
+ worker = StripSuffixString(worker, "_p");
+ }
+ if (field->is_repeated() && HasSuffixString(worker, "Array")) {
+ worker = StripSuffixString(worker, "Array");
+ }
+ if (field->type() == FieldDescriptor::TYPE_GROUP) {
+ if (worker.length() > 0) {
+ if (worker[0] >= 'a' && worker[0] <= 'z') {
+ worker[0] = ToUpper(worker[0]);
+ }
+ }
+ return worker;
+ } else {
+ string result;
+ for (int i = 0; i < worker.size(); i++) {
+ char c = worker[i];
+ if (c >= 'A' && c <= 'Z') {
+ if (i > 0) {
+ result += '_';
+ }
+ result += ToLower(c);
+ } else {
+ result += c;
+ }
+ }
+ return result;
+ }
+}
+
+string GetCapitalizedType(const FieldDescriptor* field) {
+ switch (field->type()) {
+ case FieldDescriptor::TYPE_INT32:
+ return "Int32";
+ case FieldDescriptor::TYPE_UINT32:
+ return "UInt32";
+ case FieldDescriptor::TYPE_SINT32:
+ return "SInt32";
+ case FieldDescriptor::TYPE_FIXED32:
+ return "Fixed32";
+ case FieldDescriptor::TYPE_SFIXED32:
+ return "SFixed32";
+ case FieldDescriptor::TYPE_INT64:
+ return "Int64";
+ case FieldDescriptor::TYPE_UINT64:
+ return "UInt64";
+ case FieldDescriptor::TYPE_SINT64:
+ return "SInt64";
+ case FieldDescriptor::TYPE_FIXED64:
+ return "Fixed64";
+ case FieldDescriptor::TYPE_SFIXED64:
+ return "SFixed64";
+ case FieldDescriptor::TYPE_FLOAT:
+ return "Float";
+ case FieldDescriptor::TYPE_DOUBLE:
+ return "Double";
+ case FieldDescriptor::TYPE_BOOL:
+ return "Bool";
+ case FieldDescriptor::TYPE_STRING:
+ return "String";
+ case FieldDescriptor::TYPE_BYTES:
+ return "Bytes";
+ case FieldDescriptor::TYPE_ENUM:
+ return "Enum";
+ case FieldDescriptor::TYPE_GROUP:
+ return "Group";
+ case FieldDescriptor::TYPE_MESSAGE:
+ return "Message";
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type) {
+ switch (field_type) {
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_SFIXED32:
+ return OBJECTIVECTYPE_INT32;
+
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_FIXED32:
+ return OBJECTIVECTYPE_UINT32;
+
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_SFIXED64:
+ return OBJECTIVECTYPE_INT64;
+
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_FIXED64:
+ return OBJECTIVECTYPE_UINT64;
+
+ case FieldDescriptor::TYPE_FLOAT:
+ return OBJECTIVECTYPE_FLOAT;
+
+ case FieldDescriptor::TYPE_DOUBLE:
+ return OBJECTIVECTYPE_DOUBLE;
+
+ case FieldDescriptor::TYPE_BOOL:
+ return OBJECTIVECTYPE_BOOLEAN;
+
+ case FieldDescriptor::TYPE_STRING:
+ return OBJECTIVECTYPE_STRING;
+
+ case FieldDescriptor::TYPE_BYTES:
+ return OBJECTIVECTYPE_DATA;
+
+ case FieldDescriptor::TYPE_ENUM:
+ return OBJECTIVECTYPE_ENUM;
+
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_MESSAGE:
+ return OBJECTIVECTYPE_MESSAGE;
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return OBJECTIVECTYPE_INT32;
+}
+
+bool IsPrimitiveType(const FieldDescriptor* field) {
+ ObjectiveCType type = GetObjectiveCType(field);
+ switch (type) {
+ case OBJECTIVECTYPE_INT32:
+ case OBJECTIVECTYPE_UINT32:
+ case OBJECTIVECTYPE_INT64:
+ case OBJECTIVECTYPE_UINT64:
+ case OBJECTIVECTYPE_FLOAT:
+ case OBJECTIVECTYPE_DOUBLE:
+ case OBJECTIVECTYPE_BOOLEAN:
+ case OBJECTIVECTYPE_ENUM:
+ return true;
+ break;
+ default:
+ return false;
+ }
+}
+
+bool IsReferenceType(const FieldDescriptor* field) {
+ return !IsPrimitiveType(field);
+}
+
+static string HandleExtremeFloatingPoint(string val, bool add_float_suffix) {
+ if (val == "nan") {
+ return "NAN";
+ } else if (val == "inf") {
+ return "INFINITY";
+ } else if (val == "-inf") {
+ return "-INFINITY";
+ } else {
+ // float strings with ., e or E need to have f appended
+ if (add_float_suffix &&
+ (val.find(".") != string::npos || val.find("e") != string::npos ||
+ val.find("E") != string::npos)) {
+ val += "f";
+ }
+ return val;
+ }
+}
+
+string GPBGenericValueFieldName(const FieldDescriptor* field) {
+ // Returns the field within the GPBGenericValue union to use for the given
+ // field.
+ if (field->is_repeated()) {
+ return "valueMessage";
+ }
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ return "valueInt32";
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return "valueUInt32";
+ case FieldDescriptor::CPPTYPE_INT64:
+ return "valueInt64";
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return "valueUInt64";
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return "valueFloat";
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return "valueDouble";
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return "valueBool";
+ case FieldDescriptor::CPPTYPE_STRING:
+ if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ return "valueData";
+ } else {
+ return "valueString";
+ }
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return "valueEnum";
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return "valueMessage";
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+
+string DefaultValue(const FieldDescriptor* field) {
+ // Repeated fields don't have defaults.
+ if (field->is_repeated()) {
+ return "nil";
+ }
+
+ // Switch on cpp_type since we need to know which default_value_* method
+ // of FieldDescriptor to call.
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ // gcc and llvm reject the decimal form of kint32min and kint64min.
+ if (field->default_value_int32() == INT_MIN) {
+ return "-0x80000000";
+ }
+ return SimpleItoa(field->default_value_int32());
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return SimpleItoa(field->default_value_uint32()) + "U";
+ case FieldDescriptor::CPPTYPE_INT64:
+ // gcc and llvm reject the decimal form of kint32min and kint64min.
+ if (field->default_value_int64() == LLONG_MIN) {
+ return "-0x8000000000000000LL";
+ }
+ return SimpleItoa(field->default_value_int64()) + "LL";
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return SimpleItoa(field->default_value_uint64()) + "ULL";
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return HandleExtremeFloatingPoint(
+ SimpleDtoa(field->default_value_double()), false);
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return HandleExtremeFloatingPoint(
+ SimpleFtoa(field->default_value_float()), true);
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return field->default_value_bool() ? "YES" : "NO";
+ case FieldDescriptor::CPPTYPE_STRING: {
+ const bool has_default_value = field->has_default_value();
+ const string& default_string = field->default_value_string();
+ if (!has_default_value || default_string.length() == 0) {
+ // If the field is defined as being the empty string,
+ // then we will just assign to nil, as the empty string is the
+ // default for both strings and data.
+ return "nil";
+ }
+ if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ // We want constant fields in our data structures so we can
+ // declare them as static. To achieve this we cheat and stuff
+ // a escaped c string (prefixed with a length) into the data
+ // field, and cast it to an (NSData*) so it will compile.
+ // The runtime library knows how to handle it.
+
+ // Must convert to a standard byte order for packing length into
+ // a cstring.
+ uint32 length = ghtonl(default_string.length());
+ string bytes((const char*)&length, sizeof(length));
+ bytes.append(default_string);
+ return "(NSData*)\"" + CEscape(bytes) + "\"";
+ } else {
+ return "@\"" + EscapeTrigraphs(CEscape(default_string)) + "\"";
+ }
+ }
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return EnumValueName(field->default_value_enum());
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return "nil";
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+string BuildFlagsString(const vector<string>& strings) {
+ if (strings.size() == 0) {
+ return "0";
+ }
+ string string;
+ for (size_t i = 0; i != strings.size(); ++i) {
+ if (i > 0) {
+ string.append(" | ");
+ }
+ string.append(strings[i]);
+ }
+ return string;
+}
+
+string BuildCommentsString(const SourceLocation& location) {
+ const string& comments = location.leading_comments.empty()
+ ? location.trailing_comments
+ : location.leading_comments;
+ vector<string> lines;
+ SplitStringAllowEmpty(comments, "\n", &lines);
+ while (!lines.empty() && lines.back().empty()) {
+ lines.pop_back();
+ }
+ string prefix("//");
+ string suffix("\n");
+ string final_comments;
+ for (int i = 0; i < lines.size(); i++) {
+ // We use $ for delimiters, so replace comments with dollars with
+ // html escaped version.
+ // None of the other compilers handle this (as of this writing) but we
+ // ran into it once, so just to be safe.
+ final_comments +=
+ prefix + StringReplace(lines[i], "$", "&#36;", true) + suffix;
+ }
+ return final_comments;
+}
+
+void TextFormatDecodeData::AddString(int32 key,
+ const string& input_for_decode,
+ const string& desired_output) {
+ for (vector<DataEntry>::const_iterator i = entries_.begin();
+ i != entries_.end(); ++i) {
+ if (i->first == key) {
+ cerr << "error: duplicate key (" << key
+ << ") making TextFormat data, input: \"" << input_for_decode
+ << "\", desired: \"" << desired_output << "\"." << endl;
+ cerr.flush();
+ abort();
+ }
+ }
+
+ const string& data = TextFormatDecodeData::DecodeDataForString(
+ input_for_decode, desired_output);
+ entries_.push_back(DataEntry(key, data));
+}
+
+string TextFormatDecodeData::Data() const {
+ ostringstream data_stringstream;
+
+ if (num_entries() > 0) {
+ io::OstreamOutputStream data_outputstream(&data_stringstream);
+ io::CodedOutputStream output_stream(&data_outputstream);
+
+ output_stream.WriteVarint32(num_entries());
+ for (vector<DataEntry>::const_iterator i = entries_.begin();
+ i != entries_.end(); ++i) {
+ output_stream.WriteVarint32(i->first);
+ output_stream.WriteString(i->second);
+ }
+ }
+
+ data_stringstream.flush();
+ return data_stringstream.str();
+}
+
+namespace {
+
+// Helper to build up the decode data for a string.
+class DecodeDataBuilder {
+ public:
+ DecodeDataBuilder() { Reset(); }
+
+ bool AddCharacter(const char desired, const char input);
+ void AddUnderscore() {
+ Push();
+ need_underscore_ = true;
+ }
+ string Finish() {
+ Push();
+ return decode_data_;
+ }
+
+ private:
+ static const uint8 kAddUnderscore = 0x80;
+
+ static const uint8 kOpAsIs = 0x00;
+ static const uint8 kOpFirstUpper = 0x40;
+ static const uint8 kOpFirstLower = 0x20;
+ static const uint8 kOpAllUpper = 0x60;
+
+ static const int kMaxSegmentLen = 0x1f;
+
+ void AddChar(const char desired) {
+ ++segment_len_;
+ is_all_upper_ &= IsUpper(desired);
+ }
+
+ void Push() {
+ uint8 op = (op_ | segment_len_);
+ if (need_underscore_) op |= kAddUnderscore;
+ if (op != 0) {
+ decode_data_ += (char)op;
+ }
+ Reset();
+ }
+
+ bool AddFirst(const char desired, const char input) {
+ if (desired == input) {
+ op_ = kOpAsIs;
+ } else if (desired == ToUpper(input)) {
+ op_ = kOpFirstUpper;
+ } else if (desired == ToLower(input)) {
+ op_ = kOpFirstLower;
+ } else {
+ // Can't be transformed to match.
+ return false;
+ }
+ AddChar(desired);
+ return true;
+ }
+
+ void Reset() {
+ need_underscore_ = false;
+ op_ = 0;
+ segment_len_ = 0;
+ is_all_upper_ = true;
+ }
+
+ bool need_underscore_;
+ bool is_all_upper_;
+ uint8 op_;
+ int segment_len_;
+
+ string decode_data_;
+};
+
+bool DecodeDataBuilder::AddCharacter(const char desired, const char input) {
+ // If we've hit the max size, push to start a new segment.
+ if (segment_len_ == kMaxSegmentLen) {
+ Push();
+ }
+ if (segment_len_ == 0) {
+ return AddFirst(desired, input);
+ }
+
+ // Desired and input match...
+ if (desired == input) {
+ // If we aren't transforming it, or we're upper casing it and it is
+ // supposed to be uppercase; just add it to the segment.
+ if ((op_ != kOpAllUpper) || IsUpper(desired)) {
+ AddChar(desired);
+ return true;
+ }
+
+ // Add the current segment, and start the next one.
+ Push();
+ return AddFirst(desired, input);
+ }
+
+ // If we need to uppercase, and everything so far has been uppercase,
+ // promote op to AllUpper.
+ if ((desired == ToUpper(input)) && is_all_upper_) {
+ op_ = kOpAllUpper;
+ AddChar(desired);
+ return true;
+ }
+
+ // Give up, push and start a new segment.
+ Push();
+ return AddFirst(desired, input);
+}
+
+// If decode data can't be generated, a directive for the raw string
+// is used instead.
+string DirectDecodeString(const string& str) {
+ string result;
+ result += (char)'\0'; // Marker for full string.
+ result += str;
+ result += (char)'\0'; // End of string.
+ return result;
+}
+
+} // namespace
+
+// static
+string TextFormatDecodeData::DecodeDataForString(const string& input_for_decode,
+ const string& desired_output) {
+ if ((input_for_decode.size() == 0) || (desired_output.size() == 0)) {
+ cerr << "error: got empty string for making TextFormat data, input: \""
+ << input_for_decode << "\", desired: \"" << desired_output << "\"."
+ << endl;
+ cerr.flush();
+ abort();
+ }
+ if ((input_for_decode.find('\0') != string::npos) ||
+ (desired_output.find('\0') != string::npos)) {
+ cerr << "error: got a null char in a string for making TextFormat data,"
+ << " input: \"" << CEscape(input_for_decode) << "\", desired: \""
+ << CEscape(desired_output) << "\"." << endl;
+ cerr.flush();
+ abort();
+ }
+
+ DecodeDataBuilder builder;
+
+ // Walk the output building it from the input.
+ int x = 0;
+ for (int y = 0; y < desired_output.size(); y++) {
+ const char d = desired_output[y];
+ if (d == '_') {
+ builder.AddUnderscore();
+ continue;
+ }
+
+ if (x >= input_for_decode.size()) {
+ // Out of input, no way to encode it, just return a full decode.
+ return DirectDecodeString(desired_output);
+ }
+ if (builder.AddCharacter(d, input_for_decode[x])) {
+ ++x; // Consumed one input
+ } else {
+ // Couldn't transform for the next character, just return a full decode.
+ return DirectDecodeString(desired_output);
+ }
+ }
+
+ if (x != input_for_decode.size()) {
+ // Extra input (suffix from name sanitizing?), just return a full decode.
+ return DirectDecodeString(desired_output);
+ }
+
+ // Add the end marker.
+ return builder.Finish() + (char)'\0';
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
new file mode 100644
index 00000000..10d51a34
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
@@ -0,0 +1,173 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
+
+#include <string>
+#include <vector>
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+// Strips ".proto" or ".protodevel" from the end of a filename.
+string StripProto(const string& filename);
+
+// Returns true if the name requires a ns_returns_not_retained attribute applied
+// to it.
+bool IsRetainedName(const string& name);
+
+// Returns true if the name starts with "init" and will need to have special
+// handling under ARC.
+bool IsInitName(const string& name);
+
+// Gets the name of the file we're going to generate (sans the .pb.h
+// extension). This does not include the path to that file.
+string FileName(const FileDescriptor* file);
+
+// Gets the path of the file we're going to generate (sans the .pb.h
+// extension). The path will be dependent on the objectivec package
+// declared in the proto package.
+string FilePath(const FileDescriptor* file);
+
+// Checks the prefix for a given file and outputs any warnings/errors needed.
+void ValidateObjCClassPrefix(const FileDescriptor* file);
+
+// Gets the name of the root class we'll generate in the file. This class
+// is not meant for external consumption, but instead contains helpers that
+// the rest of the the classes need
+string FileClassName(const FileDescriptor* file);
+
+// These return the fully-qualified class name corresponding to the given
+// descriptor.
+string ClassName(const Descriptor* descriptor);
+string EnumName(const EnumDescriptor* descriptor);
+
+// Returns the fully-qualified name of the enum value corresponding to the
+// the descriptor.
+string EnumValueName(const EnumValueDescriptor* descriptor);
+
+// Returns the name of the enum value corresponding to the descriptor.
+string EnumValueShortName(const EnumValueDescriptor* descriptor);
+
+// Reverse what an enum does.
+string UnCamelCaseEnumShortName(const string& name);
+
+// Returns the name to use for the extension (used as the method off the file's
+// Root class).
+string ExtensionMethodName(const FieldDescriptor* descriptor);
+
+// Returns the transformed field name.
+string FieldName(const FieldDescriptor* field);
+string FieldNameCapitalized(const FieldDescriptor* field);
+
+// Returns the transformed oneof name.
+string OneofEnumName(const OneofDescriptor* descriptor);
+string OneofName(const OneofDescriptor* descriptor);
+string OneofNameCapitalized(const OneofDescriptor* descriptor);
+
+inline bool HasFieldPresence(const FileDescriptor* file) {
+ return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) {
+ return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+inline bool IsMapEntryMessage(const Descriptor* descriptor) {
+ return descriptor->options().map_entry();
+}
+
+// Reverse of the above.
+string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field);
+
+enum ObjectiveCType {
+ OBJECTIVECTYPE_INT32,
+ OBJECTIVECTYPE_UINT32,
+ OBJECTIVECTYPE_INT64,
+ OBJECTIVECTYPE_UINT64,
+ OBJECTIVECTYPE_FLOAT,
+ OBJECTIVECTYPE_DOUBLE,
+ OBJECTIVECTYPE_BOOLEAN,
+ OBJECTIVECTYPE_STRING,
+ OBJECTIVECTYPE_DATA,
+ OBJECTIVECTYPE_ENUM,
+ OBJECTIVECTYPE_MESSAGE
+};
+
+string GetCapitalizedType(const FieldDescriptor* field);
+
+ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type);
+
+inline ObjectiveCType GetObjectiveCType(const FieldDescriptor* field) {
+ return GetObjectiveCType(field->type());
+}
+
+bool IsPrimitiveType(const FieldDescriptor* field);
+bool IsReferenceType(const FieldDescriptor* field);
+
+string GPBGenericValueFieldName(const FieldDescriptor* field);
+string DefaultValue(const FieldDescriptor* field);
+
+string BuildFlagsString(const vector<string>& strings);
+
+string BuildCommentsString(const SourceLocation& location);
+
+// Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform
+// the input into the the expected output.
+class LIBPROTOC_EXPORT TextFormatDecodeData {
+ public:
+ TextFormatDecodeData() {}
+
+ void AddString(int32 key, const string& input_for_decode,
+ const string& desired_output);
+ size_t num_entries() const { return entries_.size(); }
+ string Data() const;
+
+ static string DecodeDataForString(const string& input_for_decode,
+ const string& desired_output);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextFormatDecodeData);
+
+ typedef std::pair<int32, string> DataEntry;
+ vector<DataEntry> entries_;
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
new file mode 100644
index 00000000..dc1cef55
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
@@ -0,0 +1,257 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+namespace {
+
+TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_RawStrings) {
+ string input_for_decode("abcdefghIJ");
+ string desired_output_for_decode;
+ string expected;
+ string result;
+
+ // Different data, can't transform.
+
+ desired_output_for_decode = "zbcdefghIJ";
+ expected = string("\0zbcdefghIJ\0", 12);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ desired_output_for_decode = "abcdezghIJ";
+ expected = string("\0abcdezghIJ\0", 12);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ // Shortened data, can't transform.
+
+ desired_output_for_decode = "abcdefghI";
+ expected = string("\0abcdefghI\0", 11);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ // Extra data, can't transform.
+
+ desired_output_for_decode = "abcdefghIJz";
+ expected = string("\0abcdefghIJz\0", 13);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+}
+
+TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_ByteCodes) {
+ string input_for_decode("abcdefghIJ");
+ string desired_output_for_decode;
+ string expected;
+ string result;
+
+ desired_output_for_decode = "abcdefghIJ";
+ expected = string("\x0A\x0", 2);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ desired_output_for_decode = "_AbcdefghIJ";
+ expected = string("\xCA\x0", 2);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ desired_output_for_decode = "ABCD__EfghI_j";
+ expected = string("\x64\x80\xC5\xA1\x0", 5);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ // Long name so multiple decode ops are needed.
+
+ input_for_decode =
+ "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000";
+ desired_output_for_decode =
+ "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000";
+ expected = string("\x04\xA5\xA4\xA2\xBF\x1F\x0E\x84\x0", 9);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+}
+
+// Death tests do not work on Windows as of yet.
+#ifdef PROTOBUF_HAS_DEATH_TEST
+TEST(ObjCHelperDeathTest, TextFormatDecodeData_DecodeDataForString_Failures) {
+ // Empty inputs.
+
+ EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("", ""),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+ EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("a", ""),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+ EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("", "a"),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+
+ // Null char in the string.
+
+ string str_with_null_char("ab\0c", 4);
+ EXPECT_EXIT(
+ TextFormatDecodeData::DecodeDataForString(str_with_null_char, "def"),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got a null char in a string for making TextFormat data, input:");
+ EXPECT_EXIT(
+ TextFormatDecodeData::DecodeDataForString("def", str_with_null_char),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got a null char in a string for making TextFormat data, input:");
+}
+#endif // PROTOBUF_HAS_DEATH_TEST
+
+TEST(ObjCHelper, TextFormatDecodeData_RawStrings) {
+ TextFormatDecodeData decode_data;
+
+ // Different data, can't transform.
+ decode_data.AddString(1, "abcdefghIJ", "zbcdefghIJ");
+ decode_data.AddString(3, "abcdefghIJ", "abcdezghIJ");
+ // Shortened data, can't transform.
+ decode_data.AddString(2, "abcdefghIJ", "abcdefghI");
+ // Extra data, can't transform.
+ decode_data.AddString(4, "abcdefghIJ", "abcdefghIJz");
+
+ EXPECT_EQ(4, decode_data.num_entries());
+
+ uint8 expected_data[] = {
+ 0x4,
+ 0x1, 0x0, 'z', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 0x0,
+ 0x3, 0x0, 'a', 'b', 'c', 'd', 'e', 'z', 'g', 'h', 'I', 'J', 0x0,
+ 0x2, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 0x0,
+ 0x4, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 'z', 0x0,
+ };
+ string expected((const char*)expected_data, sizeof(expected_data));
+
+ EXPECT_EQ(expected, decode_data.Data());
+}
+
+TEST(ObjCHelper, TextFormatDecodeData_ByteCodes) {
+ TextFormatDecodeData decode_data;
+
+ decode_data.AddString(1, "abcdefghIJ", "abcdefghIJ");
+ decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ");
+ decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ");
+ decode_data.AddString(4, "abcdefghIJ", "ABCD__EfghI_j");
+ decode_data.AddString(1000,
+ "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000",
+ "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000");
+
+ EXPECT_EQ(5, decode_data.num_entries());
+
+ uint8 expected_data[] = {
+ 0x5,
+ // All as is (00 op)
+ 0x1, 0x0A, 0x0,
+ // Underscore, upper + 9 (10 op)
+ 0x3, 0xCA, 0x0,
+ // Upper + 3 (10 op), underscore, upper + 5 (10 op)
+ 0x2, 0x44, 0xC6, 0x0,
+ // All Upper for 4 (11 op), underscore, underscore, upper + 5 (10 op),
+ // underscore, lower + 0 (01 op)
+ 0x4, 0x64, 0x80, 0xC5, 0xA1, 0x0,
+ // 2 byte key: as is + 3 (00 op), underscore, lower + 4 (01 op),
+ // underscore, lower + 3 (01 op), underscore, lower + 1 (01 op),
+ // underscore, lower + 30 (01 op), as is + 30 (00 op), as is + 13 (00
+ // op),
+ // underscore, as is + 3 (00 op)
+ 0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0,
+ };
+ string expected((const char*)expected_data, sizeof(expected_data));
+
+ EXPECT_EQ(expected, decode_data.Data());
+}
+
+
+// Death tests do not work on Windows as of yet.
+#ifdef PROTOBUF_HAS_DEATH_TEST
+TEST(ObjCHelperDeathTest, TextFormatDecodeData_Failures) {
+ TextFormatDecodeData decode_data;
+
+ // Empty inputs.
+
+ EXPECT_EXIT(decode_data.AddString(1, "", ""),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+ EXPECT_EXIT(decode_data.AddString(1, "a", ""),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+ EXPECT_EXIT(decode_data.AddString(1, "", "a"),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+
+ // Null char in the string.
+
+ string str_with_null_char("ab\0c", 4);
+ EXPECT_EXIT(
+ decode_data.AddString(1, str_with_null_char, "def"),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got a null char in a string for making TextFormat data, input:");
+ EXPECT_EXIT(
+ decode_data.AddString(1, "def", str_with_null_char),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got a null char in a string for making TextFormat data, input:");
+
+ // Duplicate keys
+
+ decode_data.AddString(1, "abcdefghIJ", "abcdefghIJ");
+ decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ");
+ decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ");
+ EXPECT_EXIT(decode_data.AddString(2, "xyz", "x_yz"),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: duplicate key \\(2\\) making TextFormat data, input:");
+}
+#endif // PROTOBUF_HAS_DEATH_TEST
+
+// TODO(thomasvl): Should probably add some unittests for all the special cases
+// of name mangling (class name, field name, enum names). Rather than doing
+// this with an ObjC test in the objectivec directory, we should be able to
+// use src/google/protobuf/compiler/importer* (like other tests) to support a
+// virtual file system to feed in protos, once we have the Descriptor tree, the
+// tests could use the helper methods for generating names and validate the
+// right things are happening.
+
+} // namespace
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
new file mode 100644
index 00000000..2987f3db
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
@@ -0,0 +1,163 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_map_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+// MapFieldGenerator uses RepeatedFieldGenerator as the parent because it
+// provides a bunch of things (no has* methods, comments for contained type,
+// etc.).
+
+namespace {
+
+const char* MapEntryTypeName(const FieldDescriptor* descriptor, bool isKey) {
+ ObjectiveCType type = GetObjectiveCType(descriptor);
+ switch (type) {
+ case OBJECTIVECTYPE_INT32:
+ return "Int32";
+ case OBJECTIVECTYPE_UINT32:
+ return "UInt32";
+ case OBJECTIVECTYPE_INT64:
+ return "Int64";
+ case OBJECTIVECTYPE_UINT64:
+ return "UInt64";
+ case OBJECTIVECTYPE_FLOAT:
+ return "Float";
+ case OBJECTIVECTYPE_DOUBLE:
+ return "Double";
+ case OBJECTIVECTYPE_BOOLEAN:
+ return "Bool";
+ case OBJECTIVECTYPE_STRING:
+ return (isKey ? "String" : "Object");
+ case OBJECTIVECTYPE_DATA:
+ return "Object";
+ case OBJECTIVECTYPE_ENUM:
+ return "Enum";
+ case OBJECTIVECTYPE_MESSAGE:
+ return "Object";
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+} // namespace
+
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor)
+ : RepeatedFieldGenerator(descriptor) {
+ const FieldDescriptor* key_descriptor =
+ descriptor->message_type()->FindFieldByName("key");
+ const FieldDescriptor* value_descriptor =
+ descriptor->message_type()->FindFieldByName("value");
+ value_field_generator_.reset(FieldGenerator::Make(value_descriptor));
+
+ // Pull over some variables_ from the value.
+ variables_["field_type"] = value_field_generator_->variable("field_type");
+ variables_["default"] = value_field_generator_->variable("default");
+ variables_["default_name"] = value_field_generator_->variable("default_name");
+
+ // Build custom field flags.
+ std::vector<string> field_flags;
+ field_flags.push_back("GPBFieldMapKey" + GetCapitalizedType(key_descriptor));
+ // Pull over the current text format custom name values that was calculated.
+ if (variables_["fieldflags"].find("GPBFieldTextFormatNameCustom") !=
+ string::npos) {
+ field_flags.push_back("GPBFieldTextFormatNameCustom");
+ }
+ // Pull over some info from the value's flags.
+ const string& value_field_flags =
+ value_field_generator_->variable("fieldflags");
+ if (value_field_flags.find("GPBFieldHasDefaultValue") != string::npos) {
+ field_flags.push_back("GPBFieldHasDefaultValue");
+ }
+ if (value_field_flags.find("GPBFieldHasEnumDescriptor") != string::npos) {
+ field_flags.push_back("GPBFieldHasEnumDescriptor");
+ }
+ variables_["fieldflags"] = BuildFlagsString(field_flags);
+
+ ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
+ if ((GetObjectiveCType(key_descriptor) == OBJECTIVECTYPE_STRING) &&
+ ((value_objc_type == OBJECTIVECTYPE_STRING) ||
+ (value_objc_type == OBJECTIVECTYPE_DATA) ||
+ (value_objc_type == OBJECTIVECTYPE_MESSAGE))) {
+ variables_["array_storage_type"] = "NSMutableDictionary";
+ } else {
+ string base_name = MapEntryTypeName(key_descriptor, true);
+ base_name += MapEntryTypeName(value_descriptor, false);
+ base_name += "Dictionary";
+ variables_["array_storage_type"] = "GPB" + base_name;
+ }
+}
+
+MapFieldGenerator::~MapFieldGenerator() {}
+
+void MapFieldGenerator::FinishInitialization(void) {
+ RepeatedFieldGenerator::FinishInitialization();
+ // Use the array_comment suport in RepeatedFieldGenerator to output what the
+ // values in the map are.
+ const FieldDescriptor* value_descriptor =
+ descriptor_->message_type()->FindFieldByName("value");
+ ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
+ if ((value_objc_type == OBJECTIVECTYPE_MESSAGE) ||
+ (value_objc_type == OBJECTIVECTYPE_DATA) ||
+ (value_objc_type == OBJECTIVECTYPE_STRING) ||
+ (value_objc_type == OBJECTIVECTYPE_ENUM)) {
+ variables_["array_comment"] =
+ "// |" + variables_["name"] + "| values are |" + value_field_generator_->variable("storage_type") + "|\n";
+ } else {
+ variables_["array_comment"] = "";
+ }
+}
+
+void MapFieldGenerator::GenerateFieldDescriptionTypeSpecific(
+ io::Printer* printer) const {
+ // Relay it to the value generator to provide enum validator, message
+ // class, etc.
+ value_field_generator_->GenerateFieldDescriptionTypeSpecific(printer);
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
new file mode 100644
index 00000000..173541f2
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
@@ -0,0 +1,64 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class MapFieldGenerator : public RepeatedFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ public:
+ virtual void FinishInitialization(void);
+ virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
+
+ protected:
+ explicit MapFieldGenerator(const FieldDescriptor* descriptor);
+ virtual ~MapFieldGenerator();
+
+ private:
+ scoped_ptr<FieldGenerator> value_field_generator_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
new file mode 100644
index 00000000..32671d42
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
@@ -0,0 +1,647 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <algorithm>
+#include <iostream>
+#include <sstream>
+
+#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/compiler/objectivec/objectivec_message.h>
+#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
+#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/stubs/stl_util.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+struct FieldOrderingByNumber {
+ inline bool operator()(const FieldDescriptor* a,
+ const FieldDescriptor* b) const {
+ return a->number() < b->number();
+ }
+};
+
+int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) {
+ // The first item in the object structure is our uint32[] for has bits.
+ // We then want to order things to make the instances as small as
+ // possible. So we follow the has bits with:
+ // 1. Bools (1 byte)
+ // 2. Anything always 4 bytes - float, *32, enums
+ // 3. Anything that is always a pointer (they will be 8 bytes on 64 bit
+ // builds and 4 bytes on 32bit builds.
+ // 4. Anything always 8 bytes - double, *64
+ //
+ // Why? Using 64bit builds as an example, this means worse case, we have
+ // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes
+ // are wasted before the 4 byte values. Then if we have an odd number of
+ // those 4 byte values, the 8 byte values will be pushed down by 32bits to
+ // keep them aligned. But the structure will end 8 byte aligned, so no
+ // waste on the end. If you did the reverse order, you could waste 4 bytes
+ // before the first 8 byte value (after the has array), then a single
+ // bool on the end would need 7 bytes of padding to make the overall
+ // structure 8 byte aligned; so 11 bytes, wasted total.
+
+ // Anything repeated is a GPB*Array/NSArray, so pointer.
+ if (descriptor->is_repeated()) {
+ return 3;
+ }
+
+ switch (descriptor->type()) {
+ // All always 8 bytes.
+ case FieldDescriptor::TYPE_DOUBLE:
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_SFIXED64:
+ case FieldDescriptor::TYPE_FIXED64:
+ return 4;
+
+ // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes
+ // depending on the build architecture.
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_MESSAGE:
+ case FieldDescriptor::TYPE_STRING:
+ case FieldDescriptor::TYPE_BYTES:
+ return 3;
+
+ // All always 4 bytes (enums are int32s).
+ case FieldDescriptor::TYPE_FLOAT:
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_SFIXED32:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_ENUM:
+ return 2;
+
+ // 1 byte.
+ case FieldDescriptor::TYPE_BOOL:
+ return 1;
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return 0;
+}
+
+struct FieldOrderingByStorageSize {
+ inline bool operator()(const FieldDescriptor* a,
+ const FieldDescriptor* b) const {
+ // Order by grouping.
+ const int order_group_a = OrderGroupForFieldDescriptor(a);
+ const int order_group_b = OrderGroupForFieldDescriptor(b);
+ if (order_group_a != order_group_b) {
+ return order_group_a < order_group_b;
+ }
+ // Within the group, order by field number (provides stable ordering).
+ return a->number() < b->number();
+ }
+};
+
+struct ExtensionRangeOrdering {
+ bool operator()(const Descriptor::ExtensionRange* a,
+ const Descriptor::ExtensionRange* b) const {
+ return a->start < b->start;
+ }
+};
+
+// Sort the fields of the given Descriptor by number into a new[]'d array
+// and return it.
+const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
+ const FieldDescriptor** fields =
+ new const FieldDescriptor* [descriptor->field_count()];
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ fields[i] = descriptor->field(i);
+ }
+ sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber());
+ return fields;
+}
+
+// Sort the fields of the given Descriptor by storage size into a new[]'d
+// array and return it.
+const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
+ const FieldDescriptor** fields =
+ new const FieldDescriptor* [descriptor->field_count()];
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ fields[i] = descriptor->field(i);
+ }
+ sort(fields, fields + descriptor->field_count(),
+ FieldOrderingByStorageSize());
+ return fields;
+}
+} // namespace
+
+MessageGenerator::MessageGenerator(const string& root_classname,
+ const Descriptor* descriptor)
+ : root_classname_(root_classname),
+ descriptor_(descriptor),
+ field_generators_(descriptor),
+ class_name_(ClassName(descriptor_)) {
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ extension_generators_.push_back(
+ new ExtensionGenerator(class_name_, descriptor_->extension(i)));
+ }
+
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i));
+ oneof_generators_.push_back(generator);
+ }
+
+ for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+ EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i));
+ enum_generators_.push_back(generator);
+ }
+
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ MessageGenerator* generator =
+ new MessageGenerator(root_classname_, descriptor_->nested_type(i));
+ nested_message_generators_.push_back(generator);
+ }
+}
+
+MessageGenerator::~MessageGenerator() {
+ STLDeleteContainerPointers(extension_generators_.begin(),
+ extension_generators_.end());
+ STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end());
+ STLDeleteContainerPointers(nested_message_generators_.begin(),
+ nested_message_generators_.end());
+ STLDeleteContainerPointers(oneof_generators_.begin(),
+ oneof_generators_.end());
+}
+
+void MessageGenerator::GenerateStaticVariablesInitialization(
+ io::Printer* printer) {
+ for (vector<ExtensionGenerator*>::iterator iter =
+ extension_generators_.begin();
+ iter != extension_generators_.end(); ++iter) {
+ (*iter)->GenerateStaticVariablesInitialization(printer);
+ }
+
+ for (vector<MessageGenerator*>::iterator iter =
+ nested_message_generators_.begin();
+ iter != nested_message_generators_.end(); ++iter) {
+ (*iter)->GenerateStaticVariablesInitialization(printer);
+ }
+}
+
+void MessageGenerator::DetermineForwardDeclarations(set<string>* fwd_decls) {
+ if (!IsMapEntryMessage(descriptor_)) {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
+ // If it is a the field is repeated, the type will be and *Array, and we
+ // don't need any forward decl.
+ if (fieldDescriptor->is_repeated()) {
+ continue;
+ }
+ field_generators_.get(fieldDescriptor)
+ .DetermineForwardDeclarations(fwd_decls);
+ }
+ }
+
+ for (vector<MessageGenerator*>::iterator iter =
+ nested_message_generators_.begin();
+ iter != nested_message_generators_.end(); ++iter) {
+ (*iter)->DetermineForwardDeclarations(fwd_decls);
+ }
+}
+
+void MessageGenerator::GenerateEnumHeader(io::Printer* printer) {
+ for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
+ iter != enum_generators_.end(); ++iter) {
+ (*iter)->GenerateHeader(printer);
+ }
+
+ for (vector<MessageGenerator*>::iterator iter =
+ nested_message_generators_.begin();
+ iter != nested_message_generators_.end(); ++iter) {
+ (*iter)->GenerateEnumHeader(printer);
+ }
+}
+
+void MessageGenerator::GenerateExtensionRegistrationSource(
+ io::Printer* printer) {
+ for (vector<ExtensionGenerator*>::iterator iter =
+ extension_generators_.begin();
+ iter != extension_generators_.end(); ++iter) {
+ (*iter)->GenerateRegistrationSource(printer);
+ }
+
+ for (vector<MessageGenerator*>::iterator iter =
+ nested_message_generators_.begin();
+ iter != nested_message_generators_.end(); ++iter) {
+ (*iter)->GenerateExtensionRegistrationSource(printer);
+ }
+}
+
+void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
+ // This a a map entry message, just recurse and do nothing directly.
+ if (IsMapEntryMessage(descriptor_)) {
+ for (vector<MessageGenerator*>::iterator iter =
+ nested_message_generators_.begin();
+ iter != nested_message_generators_.end(); ++iter) {
+ (*iter)->GenerateMessageHeader(printer);
+ }
+ return;
+ }
+
+ printer->Print(
+ "#pragma mark - $classname$\n"
+ "\n",
+ "classname", class_name_);
+
+ if (descriptor_->field_count()) {
+ scoped_array<const FieldDescriptor*> sorted_fields(
+ SortFieldsByNumber(descriptor_));
+
+ printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
+ "classname", class_name_);
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(sorted_fields[i])
+ .GenerateFieldNumberConstant(printer);
+ }
+
+ printer->Outdent();
+ printer->Print("};\n\n");
+ }
+
+ for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+ iter != oneof_generators_.end(); ++iter) {
+ (*iter)->GenerateCaseEnum(printer);
+ }
+
+ string message_comments;
+ SourceLocation location;
+ if (descriptor_->GetSourceLocation(&location)) {
+ message_comments = BuildCommentsString(location);
+ } else {
+ message_comments = "";
+ }
+
+ printer->Print(
+ "$comments$@interface $classname$ : GPBMessage\n\n",
+ "classname", class_name_,
+ "comments", message_comments);
+
+ vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0);
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (field->containing_oneof() != NULL) {
+ const int oneof_index = field->containing_oneof()->index();
+ if (!seen_oneofs[oneof_index]) {
+ seen_oneofs[oneof_index] = 1;
+ oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration(
+ printer);
+ }
+ }
+ field_generators_.get(field).GeneratePropertyDeclaration(printer);
+ }
+
+ printer->Print("@end\n\n");
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateCFunctionDeclarations(printer);
+ }
+
+ if (!oneof_generators_.empty()) {
+ for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+ iter != oneof_generators_.end(); ++iter) {
+ (*iter)->GenerateClearFunctionDeclaration(printer);
+ }
+ printer->Print("\n");
+ }
+
+ if (descriptor_->extension_count() > 0) {
+ printer->Print("@interface $classname$ (DynamicMethods)\n\n",
+ "classname", class_name_);
+ for (vector<ExtensionGenerator*>::iterator iter =
+ extension_generators_.begin();
+ iter != extension_generators_.end(); ++iter) {
+ (*iter)->GenerateMembersHeader(printer);
+ }
+ printer->Print("@end\n\n");
+ }
+
+ for (vector<MessageGenerator*>::iterator iter =
+ nested_message_generators_.begin();
+ iter != nested_message_generators_.end(); ++iter) {
+ (*iter)->GenerateMessageHeader(printer);
+ }
+}
+
+void MessageGenerator::GenerateSource(io::Printer* printer) {
+ if (!IsMapEntryMessage(descriptor_)) {
+ printer->Print(
+ "#pragma mark - $classname$\n"
+ "\n",
+ "classname", class_name_);
+
+ printer->Print("@implementation $classname$\n\n",
+ "classname", class_name_);
+
+ for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+ iter != oneof_generators_.end(); ++iter) {
+ (*iter)->GeneratePropertyImplementation(printer);
+ }
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GeneratePropertyImplementation(printer);
+ }
+
+ scoped_array<const FieldDescriptor*> sorted_fields(
+ SortFieldsByNumber(descriptor_));
+ scoped_array<const FieldDescriptor*> size_order_fields(
+ SortFieldsByStorageSize(descriptor_));
+
+ vector<const Descriptor::ExtensionRange*> sorted_extensions;
+ for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+ sorted_extensions.push_back(descriptor_->extension_range(i));
+ }
+
+ sort(sorted_extensions.begin(), sorted_extensions.end(),
+ ExtensionRangeOrdering());
+
+ // TODO(thomasvl): Finish optimizing has bit. The current behavior is as
+ // follows:
+ // 1. objectivec_field.cc's SetCommonFieldVariables() defaults the has_index
+ // to the field's index in the list of fields.
+ // 2. RepeatedFieldGenerator::RepeatedFieldGenerator() sets has_index to
+ // GPBNoHasBit because repeated fields & map<> fields don't use the has
+ // bit.
+ // 3. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
+ // index that groups all the elements on of the oneof.
+ // So in has_storage, we need enough bits for the single fields that aren't
+ // in any oneof, and then one int32 for each oneof (to store the field
+ // number). So we could save a little space by not using the field's index
+ // and instead make a second pass only assigning indexes for the fields
+ // that would need it. The only savings would come when messages have over
+ // a multiple of 32 fields with some number being repeated or in oneofs to
+ // drop the count below that 32 multiple; so it hasn't seemed worth doing
+ // at the moment.
+ size_t num_has_bits = descriptor_->field_count();
+ size_t sizeof_has_storage = (num_has_bits + 31) / 32;
+ // Tell all the fields the oneof base.
+ for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+ iter != oneof_generators_.end(); ++iter) {
+ (*iter)->SetOneofIndexBase(sizeof_has_storage);
+ }
+ field_generators_.SetOneofIndexBase(sizeof_has_storage);
+ // Add an int32 for each oneof to store which is set.
+ sizeof_has_storage += descriptor_->oneof_decl_count();
+
+ printer->Print(
+ "\n"
+ "typedef struct $classname$__storage_ {\n"
+ " uint32_t _has_storage_[$sizeof_has_storage$];\n",
+ "classname", class_name_,
+ "sizeof_has_storage", SimpleItoa(sizeof_has_storage));
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(size_order_fields[i])
+ .GenerateFieldStorageDeclaration(printer);
+ }
+ printer->Outdent();
+
+ printer->Print("} $classname$__storage_;\n\n", "classname", class_name_);
+
+
+ printer->Print(
+ "// This method is threadsafe because it is initially called\n"
+ "// in +initialize for each subclass.\n"
+ "+ (GPBDescriptor *)descriptor {\n"
+ " static GPBDescriptor *descriptor = 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;
+ if (has_fields) {
+ // TODO(thomasvl): The plugin's FieldGenerator::GenerateFieldDescription()
+ // wraps the fieldOptions's value of this structure in an CPP gate so
+ // they can be compiled away; but that still results in a const char* in
+ // the structure for a NULL pointer for every message field. If the
+ // fieldOptions are moved to a separate payload like the TextFormat extra
+ // data is, then it would shrink that static data shrinking the binaries
+ // a little more.
+ // TODO(thomasvl): proto3 syntax doens't need a defaultValue in the
+ // structure because primitive types are always zero. If we add a second
+ // structure and a different initializer, we can avoid the wasted static
+ // storage for every field in a proto3 message.
+ printer->Print(
+ " static GPBMessageFieldDescription fields[] = {\n");
+ printer->Indent();
+ printer->Indent();
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); ++i) {
+ const FieldGenerator& field_generator =
+ field_generators_.get(sorted_fields[i]);
+ field_generator.GenerateFieldDescription(printer);
+ if (field_generator.needs_textformat_name_support()) {
+ text_format_decode_data.AddString(sorted_fields[i]->number(),
+ field_generator.generated_objc_name(),
+ field_generator.raw_field_name());
+ }
+ }
+ printer->Outdent();
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " };\n");
+ }
+
+ bool has_enums = enum_generators_.size();
+ if (has_enums) {
+ 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());
+ }
+ printer->Outdent();
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " };\n");
+ }
+
+ bool has_extensions = sorted_extensions.size();
+ if (has_extensions) {
+ 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));
+ }
+ printer->Outdent();
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " };\n");
+ }
+
+ map<string, string> vars;
+ vars["classname"] = class_name_;
+ vars["rootclassname"] = root_classname_;
+ vars["fields"] = has_fields ? "fields" : "NULL";
+ vars["fields_count"] =
+ has_fields ? "sizeof(fields) / sizeof(GPBMessageFieldDescription)" : "0";
+ vars["oneofs"] = has_oneofs ? "oneofs" : "NULL";
+ vars["oneof_count"] =
+ has_oneofs ? "sizeof(oneofs) / sizeof(GPBMessageOneofDescription)" : "0";
+ 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) {
+ 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");
+ }
+ 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))
+ .GenerateCFunctionImplementations(printer);
+ }
+
+ for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+ iter != oneof_generators_.end(); ++iter) {
+ (*iter)->GenerateClearFunctionImplementation(printer);
+ }
+ }
+
+ for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
+ iter != enum_generators_.end(); ++iter) {
+ (*iter)->GenerateSource(printer);
+ }
+
+ for (vector<MessageGenerator*>::iterator iter =
+ nested_message_generators_.begin();
+ iter != nested_message_generators_.end(); ++iter) {
+ (*iter)->GenerateSource(printer);
+ }
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h
new file mode 100644
index 00000000..06b536ff
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.h
@@ -0,0 +1,94 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
+
+#include <string>
+#include <set>
+#include <vector>
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/compiler/objectivec/objectivec_oneof.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+namespace io {
+class Printer; // printer.h
+} // namespace io
+
+namespace compiler {
+namespace objectivec {
+
+class ExtensionGenerator;
+class EnumGenerator;
+
+class MessageGenerator {
+ public:
+ MessageGenerator(const string& root_classname, const Descriptor* descriptor);
+ ~MessageGenerator();
+
+ void GenerateStaticVariablesInitialization(io::Printer* printer);
+ void GenerateEnumHeader(io::Printer* printer);
+ void GenerateMessageHeader(io::Printer* printer);
+ void GenerateSource(io::Printer* printer);
+ void GenerateExtensionRegistrationSource(io::Printer* printer);
+ void DetermineForwardDeclarations(set<string>* fwd_decls);
+
+ private:
+ void GenerateParseFromMethodsHeader(io::Printer* printer);
+
+ void GenerateSerializeOneFieldSource(io::Printer* printer,
+ const FieldDescriptor* field);
+ void GenerateSerializeOneExtensionRangeSource(
+ io::Printer* printer, const Descriptor::ExtensionRange* range);
+
+ void GenerateMessageDescriptionSource(io::Printer* printer);
+ void GenerateDescriptionOneFieldSource(io::Printer* printer,
+ const FieldDescriptor* field);
+
+ const string root_classname_;
+ const Descriptor* descriptor_;
+ FieldGeneratorMap field_generators_;
+ const string class_name_;
+ vector<ExtensionGenerator*> extension_generators_;
+ vector<EnumGenerator*> enum_generators_;
+ vector<MessageGenerator*> nested_message_generators_;
+ vector<OneofGenerator*> oneof_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
+};
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
new file mode 100644
index 00000000..f2ce4e5b
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
@@ -0,0 +1,96 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_message_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+void SetMessageVariables(const FieldDescriptor* descriptor,
+ map<string, string>* variables) {
+ const string& message_type = ClassName(descriptor->message_type());
+ (*variables)["type"] = message_type;
+ (*variables)["containing_class"] = ClassName(descriptor->containing_type());
+ (*variables)["storage_type"] = message_type;
+ (*variables)["group_or_message"] =
+ (descriptor->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message";
+
+ (*variables)["dataTypeSpecific_value"] = "GPBStringifySymbol(" + message_type + ")";
+}
+
+} // namespace
+
+MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor)
+ : ObjCObjFieldGenerator(descriptor) {
+ SetMessageVariables(descriptor, &variables_);
+}
+
+MessageFieldGenerator::~MessageFieldGenerator() {}
+
+void MessageFieldGenerator::DetermineForwardDeclarations(
+ set<string>* fwd_decls) const {
+ // Class name is already in "storage_type".
+ fwd_decls->insert("@class " + variable("storage_type"));
+}
+
+bool MessageFieldGenerator::WantsHasProperty(void) const {
+ if (descriptor_->containing_oneof() != NULL) {
+ // If in a oneof, it uses the oneofcase instead of a has bit.
+ return false;
+ }
+ // In both proto2 & proto3, message fields have a has* property to tell
+ // when it is a non default value.
+ return true;
+}
+
+RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
+ const FieldDescriptor* descriptor)
+ : RepeatedFieldGenerator(descriptor) {
+ SetMessageVariables(descriptor, &variables_);
+ variables_["array_storage_type"] = "NSMutableArray";
+}
+
+RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
new file mode 100644
index 00000000..708ea566
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
@@ -0,0 +1,74 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class MessageFieldGenerator : public ObjCObjFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ protected:
+ explicit MessageFieldGenerator(const FieldDescriptor* descriptor);
+ virtual ~MessageFieldGenerator();
+ virtual bool WantsHasProperty(void) const;
+
+ public:
+ virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
+};
+
+class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ protected:
+ explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor);
+ virtual ~RepeatedMessageFieldGenerator();
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
new file mode 100644
index 00000000..3cb87482
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
@@ -0,0 +1,138 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_oneof.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+OneofGenerator::OneofGenerator(const OneofDescriptor* descriptor)
+ : descriptor_(descriptor) {
+ variables_["enum_name"] = OneofEnumName(descriptor_);
+ variables_["name"] = OneofName(descriptor_);
+ variables_["capitalized_name"] = OneofNameCapitalized(descriptor_);
+ variables_["raw_index"] = SimpleItoa(descriptor_->index());
+ const Descriptor* msg_descriptor = descriptor_->containing_type();
+ variables_["owning_message_class"] = ClassName(msg_descriptor);
+
+ string comments;
+ SourceLocation location;
+ if (descriptor_->GetSourceLocation(&location)) {
+ comments = BuildCommentsString(location);
+ } else {
+ comments = "";
+ }
+ variables_["comments"] = comments;
+}
+
+OneofGenerator::~OneofGenerator() {}
+
+void OneofGenerator::SetOneofIndexBase(int index_base) {
+ int index = descriptor_->index() + index_base;
+ // Flip the sign to mark it as a oneof.
+ variables_["index"] = SimpleItoa(-index);
+}
+
+void OneofGenerator::GenerateCaseEnum(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "typedef GPB_ENUM($enum_name$) {\n");
+ printer->Indent();
+ printer->Print(
+ variables_,
+ "$enum_name$_GPBUnsetOneOfCase = 0,\n");
+ string enum_name = variables_["enum_name"];
+ for (int j = 0; j < descriptor_->field_count(); j++) {
+ const FieldDescriptor* field = descriptor_->field(j);
+ string field_name = FieldNameCapitalized(field);
+ printer->Print(
+ "$enum_name$_$field_name$ = $field_number$,\n",
+ "enum_name", enum_name,
+ "field_name", field_name,
+ "field_number", SimpleItoa(field->number()));
+ }
+ printer->Outdent();
+ printer->Print(
+ "};\n"
+ "\n");
+}
+
+void OneofGenerator::GeneratePublicCasePropertyDeclaration(
+ io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$comments$"
+ "@property(nonatomic, readonly) $enum_name$ $name$OneOfCase;\n"
+ "\n");
+}
+
+void OneofGenerator::GenerateClearFunctionDeclaration(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message);\n");
+}
+
+void OneofGenerator::GeneratePropertyImplementation(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "@dynamic $name$OneOfCase;\n");
+}
+
+void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n"
+ " GPBDescriptor *descriptor = [message descriptor];\n"
+ " GPBOneofDescriptor *oneof = descriptor->oneofs_[$raw_index$];\n"
+ " GPBMaybeClearOneof(message, oneof, 0);\n"
+ "}\n");
+}
+
+void OneofGenerator::GenerateDescription(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "{\n"
+ " .name = \"$name$\",\n"
+ " .index = $index$,\n"
+ "},\n");
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
new file mode 100644
index 00000000..bcba82da
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
@@ -0,0 +1,77 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__
+
+#include <string>
+#include <set>
+#include <vector>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+class Printer; // printer.h
+}
+}
+
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class OneofGenerator {
+ public:
+ explicit OneofGenerator(const OneofDescriptor* descriptor);
+ ~OneofGenerator();
+
+ void SetOneofIndexBase(int index_base);
+
+ void GenerateCaseEnum(io::Printer* printer);
+
+ void GeneratePublicCasePropertyDeclaration(io::Printer* printer);
+ void GenerateClearFunctionDeclaration(io::Printer* printer);
+
+ void GeneratePropertyImplementation(io::Printer* printer);
+ void GenerateClearFunctionImplementation(io::Printer* printer);
+ void GenerateDescription(io::Printer* printer);
+
+ private:
+ const OneofDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OneofGenerator);
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
new file mode 100644
index 00000000..c185b66d
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
@@ -0,0 +1,171 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+const char* PrimitiveTypeName(const FieldDescriptor* descriptor) {
+ ObjectiveCType type = GetObjectiveCType(descriptor);
+ switch (type) {
+ case OBJECTIVECTYPE_INT32:
+ return "int32_t";
+ case OBJECTIVECTYPE_UINT32:
+ return "uint32_t";
+ case OBJECTIVECTYPE_INT64:
+ return "int64_t";
+ case OBJECTIVECTYPE_UINT64:
+ return "uint64_t";
+ case OBJECTIVECTYPE_FLOAT:
+ return "float";
+ case OBJECTIVECTYPE_DOUBLE:
+ return "double";
+ case OBJECTIVECTYPE_BOOLEAN:
+ return "BOOL";
+ case OBJECTIVECTYPE_STRING:
+ return "NSString";
+ case OBJECTIVECTYPE_DATA:
+ return "NSData";
+ case OBJECTIVECTYPE_ENUM:
+ return "int32_t";
+ case OBJECTIVECTYPE_MESSAGE:
+ return NULL;
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+const char* PrimitiveArrayTypeName(const FieldDescriptor* descriptor) {
+ ObjectiveCType type = GetObjectiveCType(descriptor);
+ switch (type) {
+ case OBJECTIVECTYPE_INT32:
+ return "Int32";
+ case OBJECTIVECTYPE_UINT32:
+ return "UInt32";
+ case OBJECTIVECTYPE_INT64:
+ return "Int64";
+ case OBJECTIVECTYPE_UINT64:
+ return "UInt64";
+ case OBJECTIVECTYPE_FLOAT:
+ return "Float";
+ case OBJECTIVECTYPE_DOUBLE:
+ return "Double";
+ case OBJECTIVECTYPE_BOOLEAN:
+ return "Bool";
+ case OBJECTIVECTYPE_STRING:
+ return ""; // Want NSArray
+ case OBJECTIVECTYPE_DATA:
+ return ""; // Want NSArray
+ case OBJECTIVECTYPE_ENUM:
+ return "Enum";
+ case OBJECTIVECTYPE_MESSAGE:
+ return ""; // Want NSArray
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+ map<string, string>* variables) {
+ std::string primitive_name = PrimitiveTypeName(descriptor);
+ (*variables)["type"] = primitive_name;
+ (*variables)["storage_type"] = primitive_name;
+}
+
+} // namespace
+
+PrimitiveFieldGenerator::PrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor)
+ : SingleFieldGenerator(descriptor) {
+ SetPrimitiveVariables(descriptor, &variables_);
+}
+
+PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
+
+PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator(
+ const FieldDescriptor* descriptor)
+ : ObjCObjFieldGenerator(descriptor) {
+ SetPrimitiveVariables(descriptor, &variables_);
+ variables_["property_storage_attribute"] = "copy";
+}
+
+PrimitiveObjFieldGenerator::~PrimitiveObjFieldGenerator() {}
+
+RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor)
+ : RepeatedFieldGenerator(descriptor) {
+ SetPrimitiveVariables(descriptor, &variables_);
+
+ string base_name = PrimitiveArrayTypeName(descriptor);
+ if (base_name.length()) {
+ variables_["array_storage_type"] = "GPB" + base_name + "Array";
+ } else {
+ variables_["array_storage_type"] = "NSMutableArray";
+ }
+}
+
+RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
+
+void RepeatedPrimitiveFieldGenerator::FinishInitialization(void) {
+ RepeatedFieldGenerator::FinishInitialization();
+ if (IsPrimitiveType(descriptor_)) {
+ // No comment needed for primitive types.
+ variables_["array_comment"] = "";
+ }
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
new file mode 100644
index 00000000..9bb79343
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
@@ -0,0 +1,82 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class PrimitiveFieldGenerator : public SingleFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ protected:
+ explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+ virtual ~PrimitiveFieldGenerator();
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
+};
+
+class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ protected:
+ explicit PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor);
+ virtual ~PrimitiveObjFieldGenerator();
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveObjFieldGenerator);
+};
+
+class RepeatedPrimitiveFieldGenerator : public RepeatedFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ protected:
+ explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+ virtual ~RepeatedPrimitiveFieldGenerator();
+ virtual void FinishInitialization(void);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index fe697acf..a2eeee2d 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -277,27 +277,39 @@ bool Parser::ConsumeString(string* output, const char* error) {
}
}
-bool Parser::TryConsumeEndOfDeclaration(const char* text,
- const LocationRecorder* location) {
+bool Parser::TryConsumeEndOfDeclaration(
+ const char* text, const LocationRecorder* location) {
if (LookingAt(text)) {
string leading, trailing;
- input_->NextWithComments(&trailing, NULL, &leading);
+ vector<string> detached;
+ input_->NextWithComments(&trailing, &detached, &leading);
// Save the leading comments for next time, and recall the leading comments
// from last time.
leading.swap(upcoming_doc_comments_);
if (location != NULL) {
- location->AttachComments(&leading, &trailing);
+ upcoming_detached_comments_.swap(detached);
+ location->AttachComments(&leading, &trailing, &detached);
+ } else if (strcmp(text, "}") == 0) {
+ // If the current location is null and we are finishing the current scope,
+ // drop pending upcoming detached comments.
+ upcoming_detached_comments_.swap(detached);
+ } else {
+ // Otherwise, append the new detached comments to the existing upcoming
+ // detached comments.
+ upcoming_detached_comments_.insert(upcoming_detached_comments_.end(),
+ detached.begin(), detached.end());
}
+
return true;
} else {
return false;
}
}
-bool Parser::ConsumeEndOfDeclaration(const char* text,
- const LocationRecorder* location) {
+bool Parser::ConsumeEndOfDeclaration(
+ const char* text, const LocationRecorder* location) {
if (TryConsumeEndOfDeclaration(text, location)) {
return true;
} else {
@@ -390,7 +402,8 @@ void Parser::LocationRecorder::RecordLegacyLocation(const Message* descriptor,
}
void Parser::LocationRecorder::AttachComments(
- string* leading, string* trailing) const {
+ string* leading, string* trailing,
+ vector<string>* detached_comments) const {
GOOGLE_CHECK(!location_->has_leading_comments());
GOOGLE_CHECK(!location_->has_trailing_comments());
@@ -400,6 +413,11 @@ void Parser::LocationRecorder::AttachComments(
if (!trailing->empty()) {
location_->mutable_trailing_comments()->swap(*trailing);
}
+ for (int i = 0; i < detached_comments->size(); ++i) {
+ location_->add_leading_detached_comments()->swap(
+ (*detached_comments)[i]);
+ }
+ detached_comments->clear();
}
// -------------------------------------------------------------------
@@ -451,16 +469,18 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
SourceCodeInfo source_code_info;
source_code_info_ = &source_code_info;
+ vector<string> top_doc_comments;
if (LookingAtType(io::Tokenizer::TYPE_START)) {
// Advance to first token.
- input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_);
+ input_->NextWithComments(NULL, &upcoming_detached_comments_,
+ &upcoming_doc_comments_);
}
{
LocationRecorder root_location(this);
if (require_syntax_identifier_ || LookingAt("syntax")) {
- if (!ParseSyntaxIdentifier()) {
+ if (!ParseSyntaxIdentifier(root_location)) {
// Don't attempt to parse the file if we didn't recognize the syntax
// identifier.
return false;
@@ -469,9 +489,9 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
if (file != NULL) file->set_syntax(syntax_identifier_);
} else if (!stop_after_syntax_identifier_) {
GOOGLE_LOG(WARNING) << "No syntax specified for the proto file. "
- << "Please use 'syntax = \"proto2\";' or "
- << "'syntax = \"proto3\";' to specify a syntax "
- << "version. (Defaulted to proto2 syntax.)";
+ << "Please use 'syntax = \"proto2\";' or "
+ << "'syntax = \"proto3\";' to specify a syntax "
+ << "version. (Defaulted to proto2 syntax.)";
syntax_identifier_ = "proto2";
}
@@ -486,7 +506,8 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
if (LookingAt("}")) {
AddError("Unmatched \"}\".");
- input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_);
+ input_->NextWithComments(NULL, &upcoming_detached_comments_,
+ &upcoming_doc_comments_);
}
}
}
@@ -498,7 +519,9 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
return !had_errors_;
}
-bool Parser::ParseSyntaxIdentifier() {
+bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) {
+ LocationRecorder syntax_location(parent,
+ FileDescriptorProto::kSyntaxFieldNumber);
DO(Consume(
"syntax",
"File must begin with a syntax statement, e.g. 'syntax = \"proto2\";'."));
@@ -506,7 +529,7 @@ bool Parser::ParseSyntaxIdentifier() {
io::Tokenizer::Token syntax_token = input_->current();
string syntax;
DO(ConsumeString(&syntax, "Expected syntax identifier."));
- DO(ConsumeEndOfDeclaration(";", NULL));
+ DO(ConsumeEndOfDeclaration(";", &syntax_location));
syntax_identifier_ = syntax;
@@ -663,6 +686,8 @@ bool Parser::ParseMessageStatement(DescriptorProto* message,
LocationRecorder location(message_location,
DescriptorProto::kExtensionRangeFieldNumber);
return ParseExtensions(message, location, containing_file);
+ } else if (LookingAt("reserved")) {
+ return ParseReserved(message, message_location);
} else if (LookingAt("extend")) {
LocationRecorder location(message_location,
DescriptorProto::kExtensionFieldNumber);
@@ -710,6 +735,13 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field,
FieldDescriptorProto::Label label;
if (ParseLabel(&label, containing_file)) {
field->set_label(label);
+ if (label == FieldDescriptorProto::LABEL_OPTIONAL &&
+ syntax_identifier_ == "proto3") {
+ AddError(
+ "Explicit 'optional' labels are disallowed in the Proto3 syntax. "
+ "To define 'optional' fields in Proto3, simply remove the "
+ "'optional' label, as fields are 'optional' by default.");
+ }
}
}
@@ -1271,7 +1303,6 @@ bool Parser::ParseOption(Message* options,
DO(ConsumeEndOfDeclaration(";", &location));
}
-
return true;
}
@@ -1331,6 +1362,77 @@ bool Parser::ParseExtensions(DescriptorProto* message,
return true;
}
+// This is similar to extension range parsing, except that "max" is not
+// supported, and accepts field name literals.
+bool Parser::ParseReserved(DescriptorProto* message,
+ const LocationRecorder& message_location) {
+ // Parse the declaration.
+ DO(Consume("reserved"));
+ if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+ LocationRecorder location(message_location,
+ DescriptorProto::kReservedNameFieldNumber);
+ return ParseReservedNames(message, location);
+ } else {
+ LocationRecorder location(message_location,
+ DescriptorProto::kReservedRangeFieldNumber);
+ return ParseReservedNumbers(message, location);
+ }
+}
+
+
+bool Parser::ParseReservedNames(DescriptorProto* message,
+ const LocationRecorder& parent_location) {
+ do {
+ LocationRecorder location(parent_location, message->reserved_name_size());
+ DO(ConsumeString(message->add_reserved_name(), "Expected field name."));
+ } while (TryConsume(","));
+ DO(ConsumeEndOfDeclaration(";", &parent_location));
+ return true;
+}
+
+bool Parser::ParseReservedNumbers(DescriptorProto* message,
+ const LocationRecorder& parent_location) {
+ bool first = true;
+ do {
+ LocationRecorder location(parent_location, message->reserved_range_size());
+
+ DescriptorProto::ReservedRange* range = message->add_reserved_range();
+ int start, end;
+ io::Tokenizer::Token start_token;
+ {
+ LocationRecorder start_location(
+ location, DescriptorProto::ReservedRange::kStartFieldNumber);
+ start_token = input_->current();
+ DO(ConsumeInteger(&start, (first ?
+ "Expected field name or number range." :
+ "Expected field number range.")));
+ }
+
+ if (TryConsume("to")) {
+ LocationRecorder end_location(
+ location, DescriptorProto::ReservedRange::kEndFieldNumber);
+ DO(ConsumeInteger(&end, "Expected integer."));
+ } else {
+ LocationRecorder end_location(
+ location, DescriptorProto::ReservedRange::kEndFieldNumber);
+ end_location.StartAt(start_token);
+ end_location.EndAt(start_token);
+ end = start;
+ }
+
+ // Users like to specify inclusive ranges, but in code we like the end
+ // number to be exclusive.
+ ++end;
+
+ range->set_start(start);
+ range->set_end(end);
+ first = false;
+ } while (TryConsume(","));
+
+ DO(ConsumeEndOfDeclaration(";", &parent_location));
+ return true;
+}
+
bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
RepeatedPtrField<DescriptorProto>* messages,
const LocationRecorder& parent_location,
@@ -1636,8 +1738,14 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method,
// Parse input type.
DO(Consume("("));
{
- if (TryConsume("stream")) {
+ if (LookingAt("stream")) {
+ LocationRecorder location(
+ method_location, MethodDescriptorProto::kClientStreamingFieldNumber);
+ location.RecordLegacyLocation(
+ method, DescriptorPool::ErrorCollector::OTHER);
method->set_client_streaming(true);
+ DO(Consume("stream"));
+
}
LocationRecorder location(method_location,
MethodDescriptorProto::kInputTypeFieldNumber);
@@ -1651,8 +1759,14 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method,
DO(Consume("returns"));
DO(Consume("("));
{
- if (TryConsume("stream")) {
+ if (LookingAt("stream")) {
+ LocationRecorder location(
+ method_location, MethodDescriptorProto::kServerStreamingFieldNumber);
+ location.RecordLegacyLocation(
+ method, DescriptorPool::ErrorCollector::OTHER);
+ DO(Consume("stream"));
method->set_server_streaming(true);
+
}
LocationRecorder location(method_location,
MethodDescriptorProto::kOutputTypeFieldNumber);
@@ -1664,10 +1778,9 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method,
if (LookingAt("{")) {
// Options!
- DO(ParseOptions(method_location,
- containing_file,
- MethodDescriptorProto::kOptionsFieldNumber,
- method->mutable_options()));
+ DO(ParseMethodOptions(method_location, containing_file,
+ MethodDescriptorProto::kOptionsFieldNumber,
+ method->mutable_options()));
} else {
DO(ConsumeEndOfDeclaration(";", &method_location));
}
@@ -1676,10 +1789,10 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method,
}
-bool Parser::ParseOptions(const LocationRecorder& parent_location,
- const FileDescriptorProto* containing_file,
- const int optionsFieldNumber,
- Message* mutable_options) {
+bool Parser::ParseMethodOptions(const LocationRecorder& parent_location,
+ const FileDescriptorProto* containing_file,
+ const int optionsFieldNumber,
+ Message* mutable_options) {
// Options!
ConsumeEndOfDeclaration("{", &parent_location);
while (!TryConsumeEndOfDeclaration("}", NULL)) {
@@ -1693,8 +1806,8 @@ bool Parser::ParseOptions(const LocationRecorder& parent_location,
} else {
LocationRecorder location(parent_location,
optionsFieldNumber);
- if (!ParseOption(mutable_options, location, containing_file,
- OPTION_STATEMENT)) {
+ if (!ParseOption(mutable_options, location,
+ containing_file, OPTION_STATEMENT)) {
// This statement failed to parse. Skip it, but keep looping to
// parse other statements.
SkipStatement();
@@ -1847,7 +1960,7 @@ bool SourceLocationTable::Find(
DescriptorPool::ErrorCollector::ErrorLocation location,
int* line, int* column) const {
const pair<int, int>* result =
- FindOrNull(location_map_, make_pair(descriptor, location));
+ FindOrNull(location_map_, std::make_pair(descriptor, location));
if (result == NULL) {
*line = -1;
*column = 0;
@@ -1863,7 +1976,8 @@ void SourceLocationTable::Add(
const Message* descriptor,
DescriptorPool::ErrorCollector::ErrorLocation location,
int line, int column) {
- location_map_[make_pair(descriptor, location)] = make_pair(line, column);
+ location_map_[std::make_pair(descriptor, location)] =
+ std::make_pair(line, column);
}
void SourceLocationTable::Clear() {
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index a15cc705..16012e96 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -185,10 +185,13 @@ class LIBPROTOBUF_EXPORT Parser {
// have been passed around by const reference, for no particularly good
// reason. We should probably go through and change them all to mutable
// pointer to make this more intuitive.
- bool TryConsumeEndOfDeclaration(const char* text,
- const LocationRecorder* location);
- bool ConsumeEndOfDeclaration(const char* text,
- const LocationRecorder* location);
+ bool TryConsumeEndOfDeclaration(
+ const char* text, const LocationRecorder* location);
+ bool TryConsumeEndOfDeclarationFinishScope(
+ const char* text, const LocationRecorder* location);
+
+ bool ConsumeEndOfDeclaration(
+ const char* text, const LocationRecorder* location);
// -----------------------------------------------------------------
// Error logging helpers
@@ -253,9 +256,13 @@ class LIBPROTOBUF_EXPORT Parser {
//
// TODO(kenton): See comment on TryConsumeEndOfDeclaration(), above, for
// why this is const.
- void AttachComments(string* leading, string* trailing) const;
+ void AttachComments(string* leading, string* trailing,
+ vector<string>* detached_comments) const;
private:
+ // Indexes of parent and current location in the parent
+ // SourceCodeInfo.location repeated field. For top-level elements,
+ // parent_index_ is -1.
Parser* parser_;
SourceCodeInfo::Location* location_;
@@ -268,7 +275,7 @@ class LIBPROTOBUF_EXPORT Parser {
// Parses the "syntax = \"proto2\";" line at the top of the file. Returns
// false if it failed to parse or if the syntax identifier was not
// recognized.
- bool ParseSyntaxIdentifier();
+ bool ParseSyntaxIdentifier(const LocationRecorder& parent);
// These methods parse various individual bits of code. They return
// false if they completely fail to parse the construct. In this case,
@@ -302,9 +309,6 @@ class LIBPROTOBUF_EXPORT Parser {
RepeatedField<int32>* weak_dependency,
const LocationRecorder& root_location,
const FileDescriptorProto* containing_file);
- bool ParseOption(Message* options,
- const LocationRecorder& options_location,
- const FileDescriptorProto* containing_file);
// These methods parse the contents of a message, enum, or service type and
// add them to the given object. They consume the entire block including
@@ -360,6 +364,14 @@ class LIBPROTOBUF_EXPORT Parser {
const LocationRecorder& extensions_location,
const FileDescriptorProto* containing_file);
+ // Parse an "reserved" declaration.
+ bool ParseReserved(DescriptorProto* message,
+ const LocationRecorder& message_location);
+ bool ParseReservedNames(DescriptorProto* message,
+ const LocationRecorder& parent_location);
+ bool ParseReservedNumbers(DescriptorProto* message,
+ const LocationRecorder& parent_location);
+
// Parse an "extend" declaration. (See also comments for
// ParseMessageField().)
bool ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
@@ -397,10 +409,10 @@ class LIBPROTOBUF_EXPORT Parser {
// Parse options of a single method or stream.
- bool ParseOptions(const LocationRecorder& parent_location,
- const FileDescriptorProto* containing_file,
- const int optionsFieldNumber,
- Message* mutable_options);
+ bool ParseMethodOptions(const LocationRecorder& parent_location,
+ const FileDescriptorProto* containing_file,
+ const int optionsFieldNumber,
+ Message* mutable_options);
// Parse "required", "optional", or "repeated" and fill in "label"
// with the value. Returns true if shuch a label is consumed.
@@ -497,6 +509,13 @@ class LIBPROTOBUF_EXPORT Parser {
// yet; use ConsumeEndOfDeclaration() to get the complete comments.
string upcoming_doc_comments_;
+ // Detached comments are not connected to any syntax entities. Elements in
+ // this vector are paragraphs of comments separated by empty lines. The
+ // detached comments will be put into the leading_detached_comments field for
+ // the next element (See SourceCodeInfo.Location in descriptor.proto), when
+ // ConsumeEndOfDeclaration() is called.
+ vector<string> upcoming_detached_comments_;
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser);
};
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index 638a83b9..cc6f1efb 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -229,6 +229,32 @@ TEST_F(ParserTest, WarnIfSyntaxIdentifierOmmitted) {
typedef ParserTest ParseMessageTest;
+TEST_F(ParseMessageTest, IgnoreBOM) {
+ char input[] = " message TestMessage {\n"
+ " required int32 foo = 1;\n"
+ "}\n";
+ // Set UTF-8 BOM.
+ input[0] = (char)0xEF;
+ input[1] = (char)0xBB;
+ input[2] = (char)0xBF;
+ ExpectParsesTo(input,
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, BOMError) {
+ char input[] = " message TestMessage {\n"
+ " required int32 foo = 1;\n"
+ "}\n";
+ input[0] = (char)0xEF;
+ ExpectHasErrors(input,
+ "0:1: Proto file starts with 0xEF but not UTF-8 BOM. "
+ "Only UTF-8 is accepted for proto file.\n"
+ "0:0: Expected top-level statement (e.g. \"message\").\n");
+}
+
TEST_F(ParseMessageTest, SimpleMessage) {
ExpectParsesTo(
"message TestMessage {\n"
@@ -401,13 +427,27 @@ TEST_F(ParseMessageTest, FieldDefaults) {
" field { type:TYPE_BOOL default_value:\"true\" " ETC " }"
" field { type_name:\"Foo\" default_value:\"FOO\" " ETC " }"
- " field { type:TYPE_INT32 default_value:\"2147483647\" " ETC " }"
- " field { type:TYPE_INT32 default_value:\"-2147483648\" " ETC " }"
- " field { type:TYPE_UINT32 default_value:\"4294967295\" " ETC " }"
- " field { type:TYPE_INT64 default_value:\"9223372036854775807\" " ETC " }"
- " field { type:TYPE_INT64 default_value:\"-9223372036854775808\" " ETC " }"
- " field { type:TYPE_UINT64 default_value:\"18446744073709551615\" " ETC " }"
- " field { type:TYPE_DOUBLE default_value:\"43981\" " ETC " }"
+ " field {"
+ " type:TYPE_INT32 default_value:\"2147483647\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_INT32 default_value:\"-2147483648\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_UINT32 default_value:\"4294967295\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_INT64 default_value:\"9223372036854775807\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_INT64 default_value:\"-9223372036854775808\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_UINT64 default_value:\"18446744073709551615\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_DOUBLE default_value:\"43981\" " ETC
+ " }"
"}");
#undef ETC
}
@@ -606,6 +646,36 @@ TEST_F(ParseMessageTest, NestedEnum) {
"}");
}
+TEST_F(ParseMessageTest, ReservedRange) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " required int32 foo = 1;\n"
+ " reserved 2, 15, 9 to 11, 3;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
+ " reserved_range { start:2 end:3 }"
+ " reserved_range { start:15 end:16 }"
+ " reserved_range { start:9 end:12 }"
+ " reserved_range { start:3 end:4 }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, ReservedNames) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " reserved \"foo\", \"bar\";\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " reserved_name: \"foo\""
+ " reserved_name: \"bar\""
+ "}");
+}
+
TEST_F(ParseMessageTest, ExtensionRange) {
ExpectParsesTo(
"message TestMessage {\n"
@@ -701,19 +771,17 @@ TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) {
" type_name:\"TestMessage\" extendee: \"Extendee1\" }");
}
-TEST_F(ParseMessageTest, OptionalOptionalLabelProto3) {
+TEST_F(ParseMessageTest, OptionalLabelProto3) {
ExpectParsesTo(
"syntax = \"proto3\";\n"
"message TestMessage {\n"
" int32 foo = 1;\n"
- " optional int32 bar = 2;\n"
"}\n",
"syntax: \"proto3\" "
"message_type {"
" name: \"TestMessage\""
- " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
- " field { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:2 } }");
+ " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 } }");
}
// ===================================================================
@@ -1216,6 +1284,18 @@ TEST_F(ParseErrorTest, EofInAggregateValue) {
"1:0: Unexpected end of stream while parsing aggregate value.\n");
}
+TEST_F(ParseErrorTest, ExplicitOptionalLabelProto3) {
+ ExpectHasErrors(
+ "syntax = 'proto3';\n"
+ "message TestMessage {\n"
+ " optional int32 foo = 1;\n"
+ "}\n",
+ "2:11: Explicit 'optional' labels are disallowed in the Proto3 syntax. "
+ "To define 'optional' fields in Proto3, simply remove the 'optional' "
+ "label, as fields are 'optional' by default.\n");
+}
+
+
// -------------------------------------------------------------------
// Enum errors
@@ -1234,6 +1314,33 @@ TEST_F(ParseErrorTest, EnumValueMissingNumber) {
}
// -------------------------------------------------------------------
+// Reserved field number errors
+
+TEST_F(ParseErrorTest, ReservedMaxNotAllowed) {
+ ExpectHasErrors(
+ "message Foo {\n"
+ " reserved 10 to max;\n"
+ "}\n",
+ "1:17: Expected integer.\n");
+}
+
+TEST_F(ParseErrorTest, ReservedMixNameAndNumber) {
+ ExpectHasErrors(
+ "message Foo {\n"
+ " reserved 10, \"foo\";\n"
+ "}\n",
+ "1:15: Expected field number range.\n");
+}
+
+TEST_F(ParseErrorTest, ReservedMissingQuotes) {
+ ExpectHasErrors(
+ "message Foo {\n"
+ " reserved foo;\n"
+ "}\n",
+ "1:11: Expected field name or number range.\n");
+}
+
+// -------------------------------------------------------------------
// Service errors
TEST_F(ParseErrorTest, EofInService) {
@@ -1557,7 +1664,7 @@ void SortMessages(DescriptorProto *descriptor_proto) {
}
DescriptorProto **data =
descriptor_proto->mutable_nested_type()->mutable_data();
- sort(data, data + size, CompareDescriptorNames());
+ std::sort(data, data + size, CompareDescriptorNames());
}
// Sorts DescriptorProtos belonging to a FileDescriptorProto, by name.
@@ -1569,7 +1676,7 @@ void SortMessages(FileDescriptorProto *file_descriptor_proto) {
}
DescriptorProto **data =
file_descriptor_proto->mutable_message_type()->mutable_data();
- sort(data, data + size, CompareDescriptorNames());
+ std::sort(data, data + size, CompareDescriptorNames());
}
// Strips the message and enum field type names for comparison purpose only.
@@ -1689,25 +1796,52 @@ TEST_F(ParseDescriptorDebugTest, TestCustomOptions) {
// places.
TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) {
SetupParser(
+ "// Detached comment before syntax.\n"
+ "\n"
+ "// Syntax comment.\n"
+ "syntax = \"proto2\";\n"
+ "\n"
+ "// Detached comment before package.\n"
+ "\n"
+ "// Package comment.\n"
+ "package comment_test;\n"
+ "\n"
+ "// Detached comment before TestMessage1.\n"
+ "\n"
"// Message comment.\n"
"message TestMessage1 {\n"
+ "\n"
+ " // Detached comment before foo.\n"
+ "\n"
" // Field comment.\n"
" optional int32 foo = 1;\n"
"\n"
+ " // Detached comment before NestedMessage.\n"
+ "\n"
" // Nested-message comment.\n"
" message NestedMessage {\n"
" optional int32 bar = 1;\n"
" }\n"
"}\n"
"\n"
+ "// Detached comment before MyEnumType.\n"
+ "\n"
"// Enum comment.\n"
"enum MyEnumType {\n"
+ "\n"
+ " // Detached comment before ASDF.\n"
+ "\n"
" // Enum-value comment.\n"
" ASDF = 1;\n"
"}\n"
"\n"
+ "// Detached comment before MyService.\n"
+ "\n"
"// Service comment.\n"
"service MyService {\n"
+ "\n"
+ " // Detached comment before MyRPCCall.\n"
+ "\n"
" // RPC comment.\n"
" rpc MyRPCCall(TestMessage1) returns (TestMessage1) { }\n"
"}\n");
@@ -1731,22 +1865,34 @@ TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) {
const string debug_string =
descriptor->DebugStringWithOptions(debug_string_options);
- // Ensure that each of the comments appears somewhere in the DebugString(),
- // and that these comments appear in order. We don't test the exact comment
- // placement or formatting, because we do not want to be too fragile here.
+ // Ensure that each of the comments appears somewhere in the DebugString().
+ // We don't test the exact comment placement or formatting, because we do not
+ // want to be too fragile here.
const char* expected_comments[] = {
+ "Detached comment before syntax.",
+ "Syntax comment.",
+ "Detached comment before package.",
+ "Package comment.",
+ "Detached comment before TestMessage1.",
"Message comment.",
+ "Detached comment before foo.",
"Field comment",
+ "Detached comment before NestedMessage.",
"Nested-message comment",
+ "Detached comment before MyEnumType.",
"Enum comment",
+ "Detached comment before ASDF.",
"Enum-value comment",
+ "Detached comment before MyService.",
"Service comment",
+ "Detached comment before MyRPCCall.",
"RPC comment",
};
for (int i = 0; i < GOOGLE_ARRAYSIZE(expected_comments); ++i) {
string::size_type found_pos = debug_string.find(expected_comments[i]);
- ASSERT_TRUE(found_pos != string::npos);
+ EXPECT_TRUE(found_pos != string::npos)
+ << "\"" << expected_comments[i] << "\" not found.";
}
}
@@ -1916,8 +2062,8 @@ class SourceInfoTest : public ParserTest {
return false;
}
- spans_.insert(make_pair(SpanKey(*descriptor_proto, field, index),
- &location));
+ spans_.insert(
+ std::make_pair(SpanKey(*descriptor_proto, field, index), &location));
}
return true;
@@ -1938,16 +2084,18 @@ class SourceInfoTest : public ParserTest {
bool HasSpan(char start_marker, char end_marker,
const Message& descriptor_proto) {
return HasSpanWithComment(
- start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL);
+ start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL, NULL);
}
bool HasSpanWithComment(char start_marker, char end_marker,
const Message& descriptor_proto,
const char* expected_leading_comments,
- const char* expected_trailing_comments) {
+ const char* expected_trailing_comments,
+ const char* expected_leading_detached_comments) {
return HasSpanWithComment(
start_marker, end_marker, descriptor_proto, NULL, -1,
- expected_leading_comments, expected_trailing_comments);
+ expected_leading_comments, expected_trailing_comments,
+ expected_leading_detached_comments);
}
bool HasSpan(char start_marker, char end_marker,
@@ -1959,14 +2107,15 @@ class SourceInfoTest : public ParserTest {
const Message& descriptor_proto, const string& field_name,
int index) {
return HasSpan(start_marker, end_marker, descriptor_proto,
- field_name, index, NULL, NULL);
+ field_name, index, NULL, NULL, NULL);
}
bool HasSpan(char start_marker, char end_marker,
const Message& descriptor_proto,
const string& field_name, int index,
const char* expected_leading_comments,
- const char* expected_trailing_comments) {
+ const char* expected_trailing_comments,
+ const char* expected_leading_detached_comments) {
const FieldDescriptor* field =
descriptor_proto.GetDescriptor()->FindFieldByName(field_name);
if (field == NULL) {
@@ -1977,12 +2126,13 @@ class SourceInfoTest : public ParserTest {
return HasSpanWithComment(
start_marker, end_marker, descriptor_proto, field, index,
- expected_leading_comments, expected_trailing_comments);
+ expected_leading_comments, expected_trailing_comments,
+ expected_leading_detached_comments);
}
bool HasSpan(const Message& descriptor_proto) {
return HasSpanWithComment(
- '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL);
+ '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL, NULL);
}
bool HasSpan(const Message& descriptor_proto, const string& field_name) {
@@ -1994,11 +2144,12 @@ class SourceInfoTest : public ParserTest {
return HasSpan('\0', '\0', descriptor_proto, field_name, index);
}
- bool HasSpanWithComment(char start_marker, char end_marker,
- const Message& descriptor_proto,
- const FieldDescriptor* field, int index,
- const char* expected_leading_comments,
- const char* expected_trailing_comments) {
+ bool HasSpanWithComment(
+ char start_marker, char end_marker, const Message& descriptor_proto,
+ const FieldDescriptor* field, int index,
+ const char* expected_leading_comments,
+ const char* expected_trailing_comments,
+ const char* expected_leading_detached_comments) {
pair<SpanMap::iterator, SpanMap::iterator> range =
spans_.equal_range(SpanKey(descriptor_proto, field, index));
@@ -2037,6 +2188,13 @@ class SourceInfoTest : public ParserTest {
EXPECT_EQ(expected_trailing_comments,
iter->second->trailing_comments());
}
+ if (expected_leading_detached_comments == NULL) {
+ EXPECT_EQ(0, iter->second->leading_detached_comments_size());
+ } else {
+ EXPECT_EQ(
+ expected_leading_detached_comments,
+ Join(iter->second->leading_detached_comments(), "\n"));
+ }
spans_.erase(iter);
return true;
@@ -2087,7 +2245,7 @@ class SourceInfoTest : public ParserTest {
text_without_markers_ += '$';
++column;
} else {
- markers_[*text] = make_pair(line, column);
+ markers_[*text] = std::make_pair(line, column);
++text;
GOOGLE_CHECK_EQ('$', *text);
}
@@ -2106,7 +2264,7 @@ class SourceInfoTest : public ParserTest {
TEST_F(SourceInfoTest, BasicFileDecls) {
EXPECT_TRUE(Parse(
- "$a$syntax = \"proto2\";\n"
+ "$a$syntax = \"proto2\";$i$\n"
"package $b$foo.bar$c$;\n"
"import $d$\"baz.proto\"$e$;\n"
"import $f$\"qux.proto\"$g$;$h$\n"
@@ -2117,6 +2275,7 @@ TEST_F(SourceInfoTest, BasicFileDecls) {
EXPECT_TRUE(HasSpan('b', 'c', file_, "package"));
EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0));
EXPECT_TRUE(HasSpan('f', 'g', file_, "dependency", 1));
+ EXPECT_TRUE(HasSpan('a', 'i', file_, "syntax"));
}
TEST_F(SourceInfoTest, Messages) {
@@ -2547,6 +2706,9 @@ TEST_F(SourceInfoTest, ScopedOptions) {
" rpc M(X) returns(Y) {\n"
" $g$option mopt = 1;$h$\n"
" }\n"
+ " rpc MS4($1$stream$2$ X) returns($3$stream$4$ Y) {\n"
+ " $k$option mopt = 1;$l$\n"
+ " }\n"
"}\n"));
EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options()));
@@ -2606,6 +2768,26 @@ TEST_F(SourceInfoTest, ScopedOptions) {
.uninterpreted_option(0).name(0), "name_part"));
EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
.uninterpreted_option(0), "positive_int_value"));
+
+ EXPECT_TRUE(HasSpan('k', 'l', file_.service(0).method(1).options()));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1)));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1), "name"));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1), "input_type"));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1), "output_type"));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+ .uninterpreted_option(0)));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+ .uninterpreted_option(0), "name"));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+ .uninterpreted_option(0).name(0)));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+ .uninterpreted_option(0).name(0), "name_part"));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+ .uninterpreted_option(0), "positive_int_value"));
+ EXPECT_TRUE(HasSpan('1', '2', file_.service(0).method(1),
+ "client_streaming"));
+ EXPECT_TRUE(HasSpan('3', '4', file_.service(0).method(1),
+ "server_streaming"));
}
TEST_F(SourceInfoTest, FieldOptions) {
@@ -2691,7 +2873,7 @@ TEST_F(SourceInfoTest, DocComments) {
" // Foo trailing\n"
" // line 2\n"
"\n"
- " // ignored\n"
+ " // detached\n"
"\n"
" // bar leading\n"
" $b$optional int32 bar = 1;$c$\n"
@@ -2705,10 +2887,12 @@ TEST_F(SourceInfoTest, DocComments) {
EXPECT_TRUE(HasSpanWithComment('a', 'd', foo,
" Foo leading\n line 2\n",
- " Foo trailing\n line 2\n"));
+ " Foo trailing\n line 2\n",
+ NULL));
EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
" bar leading\n",
- " bar trailing\n"));
+ " bar trailing\n",
+ " detached\n"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -2721,21 +2905,23 @@ TEST_F(SourceInfoTest, DocComments) {
TEST_F(SourceInfoTest, DocComments2) {
EXPECT_TRUE(Parse(
- "// ignored\n"
- "syntax = \"proto2\";\n"
+ "// detached before message.\n"
+ "\n"
"// Foo leading\n"
"// line 2\n"
"$a$message Foo {\n"
" /* Foo trailing\n"
" * line 2 */\n"
- " // ignored\n"
+ " // detached\n"
" /* bar leading\n"
" */"
" $b$optional int32 bar = 1;$c$ // bar trailing\n"
- " // ignored\n"
+ " // ignored detached\n"
"}$d$\n"
"// ignored\n"
"\n"
+ "// detached before option\n"
+ "\n"
"// option leading\n"
"$e$option baz = 123;$f$\n"
"// option trailing\n"
@@ -2747,13 +2933,16 @@ TEST_F(SourceInfoTest, DocComments2) {
EXPECT_TRUE(HasSpanWithComment('a', 'd', foo,
" Foo leading\n line 2\n",
- " Foo trailing\n line 2 "));
+ " Foo trailing\n line 2 ",
+ " detached before message.\n"));
EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
" bar leading\n",
- " bar trailing\n"));
+ " bar trailing\n",
+ " detached\n"));
EXPECT_TRUE(HasSpanWithComment('e', 'f', baz,
" option leading\n",
- " option trailing\n"));
+ " option trailing\n",
+ " detached before option\n"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -2784,7 +2973,8 @@ TEST_F(SourceInfoTest, DocComments3) {
EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
" bar leading\n",
- " bar trailing\n"));
+ " bar trailing\n",
+ NULL));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -2804,25 +2994,63 @@ TEST_F(SourceInfoTest, DocComments3) {
bar.options().uninterpreted_option(0), "aggregate_value"));
}
+TEST_F(SourceInfoTest, DocCommentsTopLevel) {
+ EXPECT_TRUE(Parse(
+ "// detached before syntax paragraph 1\n"
+ "\n"
+ "// detached before syntax paragraph 2\n"
+ "\n"
+ "// syntax leading\n"
+ "$a$syntax = \"proto2\";$b$\n"
+ "// syntax trailing\n"
+ "\n"
+ "// syntax-package detached comments\n"
+ "\n"
+ ";\n"
+ "\n"
+ "// detached after empty before package\n"
+ "\n"
+ "// package leading\n"
+ "package $c$foo$d$;\n"
+ "// package trailing\n"
+ "\n"
+ "// ignored detach\n"
+ "\n"));
+
+ EXPECT_TRUE(HasSpan('a', 'b', file_, "syntax", -1,
+ " syntax leading\n",
+ " syntax trailing\n",
+ " detached before syntax paragraph 1\n"
+ "\n"
+ " detached before syntax paragraph 2\n"));
+ EXPECT_TRUE(HasSpan('c', 'd', file_, "package", -1,
+ " package leading\n",
+ " package trailing\n",
+ " syntax-package detached comments\n"
+ "\n"
+ " detached after empty before package\n"));
+
+ // ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+}
+
TEST_F(SourceInfoTest, DocCommentsOneof) {
EXPECT_TRUE(Parse(
- "// ignored\n"
- "syntax = \"proto2\";\n"
"// Foo leading\n"
"$a$message Foo {\n"
" /* Foo trailing\n"
" */\n"
- " // ignored\n"
+ " // detached before oneof\n"
" /* bar leading\n"
" * line 2 */\n"
" $b$oneof bar {\n"
" /* bar trailing\n"
" * line 2 */\n"
- " // ignored\n"
+ " // detached before bar_int\n"
" /* bar_int leading\n"
" */\n"
" $c$int32 bar_int = 1;$d$ // bar_int trailing\n"
- " // ignored\n"
+ " // detach comment ignored\n"
" }$e$\n"
"}$f$\n"));
@@ -2832,13 +3060,16 @@ TEST_F(SourceInfoTest, DocCommentsOneof) {
EXPECT_TRUE(HasSpanWithComment('a', 'f', foo,
" Foo leading\n",
- " Foo trailing\n"));
+ " Foo trailing\n",
+ NULL));
EXPECT_TRUE(HasSpanWithComment('b', 'e', bar,
" bar leading\n line 2 ",
- " bar trailing\n line 2 "));
+ " bar trailing\n line 2 ",
+ " detached before oneof\n"));
EXPECT_TRUE(HasSpanWithComment('c', 'd', bar_int,
" bar_int leading\n",
- " bar_int trailing\n"));
+ " bar_int trailing\n",
+ " detached before bar_int\n"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
index 9011a6bd..cdcaffde 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -95,7 +95,7 @@ class GeneratorResponseContext : public GeneratorContext {
int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
if (argc > 1) {
- cerr << argv[0] << ": Unknown option: " << argv[1] << endl;
+ std::cerr << argv[0] << ": Unknown option: " << argv[1] << std::endl;
return 1;
}
@@ -106,7 +106,8 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
CodeGeneratorRequest request;
if (!request.ParseFromFileDescriptor(STDIN_FILENO)) {
- cerr << argv[0] << ": protoc sent unparseable request to plugin." << endl;
+ std::cerr << argv[0] << ": protoc sent unparseable request to plugin."
+ << std::endl;
return 1;
}
@@ -123,9 +124,9 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
for (int i = 0; i < request.file_to_generate_size(); i++) {
parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i)));
if (parsed_files.back() == NULL) {
- cerr << argv[0] << ": protoc asked plugin to generate a file but "
- "did not provide a descriptor for the file: "
- << request.file_to_generate(i) << endl;
+ std::cerr << argv[0] << ": protoc asked plugin to generate a file but "
+ "did not provide a descriptor for the file: "
+ << request.file_to_generate(i) << std::endl;
return 1;
}
}
@@ -133,25 +134,39 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
CodeGeneratorResponse response;
GeneratorResponseContext context(&response, parsed_files);
- for (int i = 0; i < parsed_files.size(); i++) {
- const FileDescriptor* file = parsed_files[i];
-
+ if (generator->HasGenerateAll()) {
string error;
- bool succeeded = generator->Generate(
- file, request.parameter(), &context, &error);
+ bool succeeded = generator->GenerateAll(
+ parsed_files, request.parameter(), &context, &error);
if (!succeeded && error.empty()) {
error = "Code generator returned false but provided no error "
"description.";
}
if (!error.empty()) {
- response.set_error(file->name() + ": " + error);
- break;
+ 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(
+ file, request.parameter(), &context, &error);
+
+ if (!succeeded && error.empty()) {
+ error = "Code generator returned false but provided no error "
+ "description.";
+ }
+ if (!error.empty()) {
+ response.set_error(file->name() + ": " + error);
+ break;
+ }
}
}
if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) {
- cerr << argv[0] << ": Error writing to stdout." << endl;
+ std::cerr << argv[0] << ": Error writing to stdout." << std::endl;
return 1;
}
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index 5118de15..e7890fae 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -140,8 +140,8 @@ void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
"\01324.google.protobuf.compiler.CodeGenerat"
"orResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022\027\n"
"\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\tB"
- ",\n\034com.google.protobuf.compilerB\014PluginP"
- "rotos", 445);
+ "7\n\034com.google.protobuf.compilerB\014PluginP"
+ "rotosZ\tplugin_go", 456);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes);
CodeGeneratorRequest::default_instance_ = new CodeGeneratorRequest();
@@ -179,7 +179,7 @@ const int CodeGeneratorRequest::kProtoFileFieldNumber;
#endif // !_MSC_VER
CodeGeneratorRequest::CodeGeneratorRequest()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest)
}
@@ -300,12 +300,15 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream(
case 15: {
if (tag == 122) {
parse_proto_file:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_proto_file:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_proto_file()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(122)) goto parse_proto_file;
+ if (input->ExpectTag(122)) goto parse_loop_proto_file;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -445,9 +448,9 @@ int CodeGeneratorRequest::ByteSize() const {
void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const CodeGeneratorRequest* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorRequest*>(
- &from);
+ const CodeGeneratorRequest* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorRequest>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -509,6 +512,147 @@ void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// CodeGeneratorRequest
+
+// repeated string file_to_generate = 1;
+int CodeGeneratorRequest::file_to_generate_size() const {
+ return file_to_generate_.size();
+}
+void CodeGeneratorRequest::clear_file_to_generate() {
+ file_to_generate_.Clear();
+}
+ const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+ return file_to_generate_.Get(index);
+}
+ ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+ return file_to_generate_.Mutable(index);
+}
+ void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+ file_to_generate_.Mutable(index)->assign(value);
+}
+ void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) {
+ file_to_generate_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) {
+ file_to_generate_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ ::std::string* CodeGeneratorRequest::add_file_to_generate() {
+ return file_to_generate_.Add();
+}
+ void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) {
+ file_to_generate_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ void CodeGeneratorRequest::add_file_to_generate(const char* value) {
+ file_to_generate_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) {
+ file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+CodeGeneratorRequest::file_to_generate() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+ return file_to_generate_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+CodeGeneratorRequest::mutable_file_to_generate() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+ return &file_to_generate_;
+}
+
+// optional string parameter = 2;
+bool CodeGeneratorRequest::has_parameter() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void CodeGeneratorRequest::set_has_parameter() {
+ _has_bits_[0] |= 0x00000002u;
+}
+void CodeGeneratorRequest::clear_has_parameter() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+void CodeGeneratorRequest::clear_parameter() {
+ parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_parameter();
+}
+ const ::std::string& CodeGeneratorRequest::parameter() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+ return parameter_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
+ set_has_parameter();
+ parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+ void CodeGeneratorRequest::set_parameter(const char* value) {
+ set_has_parameter();
+ parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+ void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
+ set_has_parameter();
+ parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+ ::std::string* CodeGeneratorRequest::mutable_parameter() {
+ set_has_parameter();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+ return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorRequest::release_parameter() {
+ clear_has_parameter();
+ return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
+ if (parameter != NULL) {
+ set_has_parameter();
+ } else {
+ clear_has_parameter();
+ }
+ parameter_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+
+// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+int CodeGeneratorRequest::proto_file_size() const {
+ return proto_file_.size();
+}
+void CodeGeneratorRequest::clear_proto_file() {
+ proto_file_.Clear();
+}
+ const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return proto_file_.Get(index);
+}
+ ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return proto_file_.Mutable(index);
+}
+ ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
+ // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return proto_file_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+CodeGeneratorRequest::proto_file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return proto_file_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+CodeGeneratorRequest::mutable_proto_file() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return &proto_file_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -519,7 +663,7 @@ const int CodeGeneratorResponse_File::kContentFieldNumber;
#endif // !_MSC_VER
CodeGeneratorResponse_File::CodeGeneratorResponse_File()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
}
@@ -583,7 +727,7 @@ CodeGeneratorResponse_File* CodeGeneratorResponse_File::New(::google::protobuf::
}
void CodeGeneratorResponse_File::Clear() {
- if (_has_bits_[0 / 32] & 7) {
+ if (_has_bits_[0 / 32] & 7u) {
if (has_name()) {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -769,7 +913,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
int CodeGeneratorResponse_File::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & 7) {
+ if (_has_bits_[0 / 32] & 7u) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -805,9 +949,9 @@ int CodeGeneratorResponse_File::ByteSize() const {
void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const CodeGeneratorResponse_File* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorResponse_File*>(
- &from);
+ const CodeGeneratorResponse_File* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse_File>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -883,7 +1027,7 @@ const int CodeGeneratorResponse::kFileFieldNumber;
#endif // !_MSC_VER
CodeGeneratorResponse::CodeGeneratorResponse()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse)
}
@@ -983,12 +1127,15 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream(
case 15: {
if (tag == 122) {
parse_file:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_file:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_file()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(122)) goto parse_file;
+ if (input->ExpectTag(122)) goto parse_loop_file;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -1101,9 +1248,9 @@ int CodeGeneratorResponse::ByteSize() const {
void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const CodeGeneratorResponse* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorResponse*>(
- &from);
+ const CodeGeneratorResponse* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -1162,6 +1309,256 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// CodeGeneratorResponse_File
+
+// optional string name = 1;
+bool CodeGeneratorResponse_File::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void CodeGeneratorResponse_File::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void CodeGeneratorResponse_File::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void CodeGeneratorResponse_File::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& CodeGeneratorResponse_File::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+ void CodeGeneratorResponse_File::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+ void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+ ::std::string* CodeGeneratorResponse_File::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorResponse_File::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+
+// optional string insertion_point = 2;
+bool CodeGeneratorResponse_File::has_insertion_point() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void CodeGeneratorResponse_File::set_has_insertion_point() {
+ _has_bits_[0] |= 0x00000002u;
+}
+void CodeGeneratorResponse_File::clear_has_insertion_point() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+void CodeGeneratorResponse_File::clear_insertion_point() {
+ insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_insertion_point();
+}
+ const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+ return insertion_point_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
+ set_has_insertion_point();
+ insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+ void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
+ set_has_insertion_point();
+ insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+ void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
+ set_has_insertion_point();
+ insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+ ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
+ set_has_insertion_point();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+ return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
+ clear_has_insertion_point();
+ return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
+ if (insertion_point != NULL) {
+ set_has_insertion_point();
+ } else {
+ clear_has_insertion_point();
+ }
+ insertion_point_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+
+// optional string content = 15;
+bool CodeGeneratorResponse_File::has_content() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void CodeGeneratorResponse_File::set_has_content() {
+ _has_bits_[0] |= 0x00000004u;
+}
+void CodeGeneratorResponse_File::clear_has_content() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+void CodeGeneratorResponse_File::clear_content() {
+ content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_content();
+}
+ const ::std::string& CodeGeneratorResponse_File::content() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+ return content_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
+ set_has_content();
+ content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+ void CodeGeneratorResponse_File::set_content(const char* value) {
+ set_has_content();
+ content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+ void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
+ set_has_content();
+ content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+ ::std::string* CodeGeneratorResponse_File::mutable_content() {
+ set_has_content();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+ return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorResponse_File::release_content() {
+ clear_has_content();
+ return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
+ if (content != NULL) {
+ set_has_content();
+ } else {
+ clear_has_content();
+ }
+ content_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+
+// -------------------------------------------------------------------
+
+// CodeGeneratorResponse
+
+// optional string error = 1;
+bool CodeGeneratorResponse::has_error() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void CodeGeneratorResponse::set_has_error() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void CodeGeneratorResponse::clear_has_error() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void CodeGeneratorResponse::clear_error() {
+ error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_error();
+}
+ const ::std::string& CodeGeneratorResponse::error() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
+ return error_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse::set_error(const ::std::string& value) {
+ set_has_error();
+ error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+ void CodeGeneratorResponse::set_error(const char* value) {
+ set_has_error();
+ error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+ void CodeGeneratorResponse::set_error(const char* value, size_t size) {
+ set_has_error();
+ error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+ ::std::string* CodeGeneratorResponse::mutable_error() {
+ set_has_error();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error)
+ return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorResponse::release_error() {
+ clear_has_error();
+ return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
+ if (error != NULL) {
+ set_has_error();
+ } else {
+ clear_has_error();
+ }
+ error_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+
+// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+int CodeGeneratorResponse::file_size() const {
+ return file_.size();
+}
+void CodeGeneratorResponse::clear_file() {
+ file_.Clear();
+}
+ const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return file_.Get(index);
+}
+ ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return file_.Mutable(index);
+}
+ ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
+ // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return file_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+CodeGeneratorResponse::file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return file_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
+CodeGeneratorResponse::mutable_file() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return &file_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index ad017005..6fcaea2e 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -110,43 +110,43 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
// accessors -------------------------------------------------------
// repeated string file_to_generate = 1;
- inline int file_to_generate_size() const;
- inline void clear_file_to_generate();
+ int file_to_generate_size() const;
+ void clear_file_to_generate();
static const int kFileToGenerateFieldNumber = 1;
- inline const ::std::string& file_to_generate(int index) const;
- inline ::std::string* mutable_file_to_generate(int index);
- inline void set_file_to_generate(int index, const ::std::string& value);
- inline void set_file_to_generate(int index, const char* value);
- inline void set_file_to_generate(int index, const char* value, size_t size);
- inline ::std::string* add_file_to_generate();
- inline void add_file_to_generate(const ::std::string& value);
- inline void add_file_to_generate(const char* value);
- inline void add_file_to_generate(const char* value, size_t size);
- inline const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const;
- inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate();
+ const ::std::string& file_to_generate(int index) const;
+ ::std::string* mutable_file_to_generate(int index);
+ void set_file_to_generate(int index, const ::std::string& value);
+ void set_file_to_generate(int index, const char* value);
+ void set_file_to_generate(int index, const char* value, size_t size);
+ ::std::string* add_file_to_generate();
+ void add_file_to_generate(const ::std::string& value);
+ void add_file_to_generate(const char* value);
+ void add_file_to_generate(const char* value, size_t size);
+ const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const;
+ ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate();
// optional string parameter = 2;
- inline bool has_parameter() const;
- inline void clear_parameter();
+ bool has_parameter() const;
+ void clear_parameter();
static const int kParameterFieldNumber = 2;
- inline const ::std::string& parameter() const;
- inline void set_parameter(const ::std::string& value);
- inline void set_parameter(const char* value);
- inline void set_parameter(const char* value, size_t size);
- inline ::std::string* mutable_parameter();
- inline ::std::string* release_parameter();
- inline void set_allocated_parameter(::std::string* parameter);
+ const ::std::string& parameter() const;
+ void set_parameter(const ::std::string& value);
+ void set_parameter(const char* value);
+ void set_parameter(const char* value, size_t size);
+ ::std::string* mutable_parameter();
+ ::std::string* release_parameter();
+ void set_allocated_parameter(::std::string* parameter);
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
- inline int proto_file_size() const;
- inline void clear_proto_file();
+ int proto_file_size() const;
+ void clear_proto_file();
static const int kProtoFileFieldNumber = 15;
- inline const ::google::protobuf::FileDescriptorProto& proto_file(int index) const;
- inline ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index);
- inline ::google::protobuf::FileDescriptorProto* add_proto_file();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+ const ::google::protobuf::FileDescriptorProto& proto_file(int index) const;
+ ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index);
+ ::google::protobuf::FileDescriptorProto* add_proto_file();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
proto_file() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
mutable_proto_file();
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
@@ -234,40 +234,40 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// optional string insertion_point = 2;
- inline bool has_insertion_point() const;
- inline void clear_insertion_point();
+ bool has_insertion_point() const;
+ void clear_insertion_point();
static const int kInsertionPointFieldNumber = 2;
- inline const ::std::string& insertion_point() const;
- inline void set_insertion_point(const ::std::string& value);
- inline void set_insertion_point(const char* value);
- inline void set_insertion_point(const char* value, size_t size);
- inline ::std::string* mutable_insertion_point();
- inline ::std::string* release_insertion_point();
- inline void set_allocated_insertion_point(::std::string* insertion_point);
+ const ::std::string& insertion_point() const;
+ void set_insertion_point(const ::std::string& value);
+ void set_insertion_point(const char* value);
+ void set_insertion_point(const char* value, size_t size);
+ ::std::string* mutable_insertion_point();
+ ::std::string* release_insertion_point();
+ void set_allocated_insertion_point(::std::string* insertion_point);
// optional string content = 15;
- inline bool has_content() const;
- inline void clear_content();
+ bool has_content() const;
+ void clear_content();
static const int kContentFieldNumber = 15;
- inline const ::std::string& content() const;
- inline void set_content(const ::std::string& value);
- inline void set_content(const char* value);
- inline void set_content(const char* value, size_t size);
- inline ::std::string* mutable_content();
- inline ::std::string* release_content();
- inline void set_allocated_content(::std::string* content);
+ const ::std::string& content() const;
+ void set_content(const ::std::string& value);
+ void set_content(const char* value);
+ void set_content(const char* value, size_t size);
+ ::std::string* mutable_content();
+ ::std::string* release_content();
+ void set_allocated_content(::std::string* content);
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
private:
@@ -360,27 +360,27 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
// accessors -------------------------------------------------------
// optional string error = 1;
- inline bool has_error() const;
- inline void clear_error();
+ bool has_error() const;
+ void clear_error();
static const int kErrorFieldNumber = 1;
- inline const ::std::string& error() const;
- inline void set_error(const ::std::string& value);
- inline void set_error(const char* value);
- inline void set_error(const char* value, size_t size);
- inline ::std::string* mutable_error();
- inline ::std::string* release_error();
- inline void set_allocated_error(::std::string* error);
+ const ::std::string& error() const;
+ void set_error(const ::std::string& value);
+ void set_error(const char* value);
+ void set_error(const char* value, size_t size);
+ ::std::string* mutable_error();
+ ::std::string* release_error();
+ void set_allocated_error(::std::string* error);
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
- inline int file_size() const;
- inline void clear_file();
+ int file_size() const;
+ void clear_file();
static const int kFileFieldNumber = 15;
- inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const;
- inline ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index);
- inline ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+ const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const;
+ ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index);
+ ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
file() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
mutable_file();
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
@@ -405,6 +405,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
// ===================================================================
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
// CodeGeneratorRequest
// repeated string file_to_generate = 1;
@@ -794,21 +795,17 @@ CodeGeneratorResponse::mutable_file() {
return &file_;
}
+#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
-// @@protoc_insertion_point(namespace_scope)
-
-} // namespace compiler
-} // namespace protobuf
-} // namespace google
+// -------------------------------------------------------------------
-#ifndef SWIG
-namespace google {
-namespace protobuf {
+// @@protoc_insertion_point(namespace_scope)
+} // namespace compiler
} // namespace protobuf
} // namespace google
-#endif // SWIG
// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto
index e627289b..acaee1f4 100644
--- a/src/google/protobuf/compiler/plugin.proto
+++ b/src/google/protobuf/compiler/plugin.proto
@@ -49,6 +49,8 @@ package google.protobuf.compiler;
option java_package = "com.google.protobuf.compiler";
option java_outer_classname = "PluginProtos";
+option go_package = "plugin_go";
+
import "google/protobuf/descriptor.proto";
// An encoded CodeGeneratorRequest is written to the plugin's stdin.
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index b30d1972..7b3b5fa3 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -273,6 +273,19 @@ string StringifyDefaultValue(const FieldDescriptor& field) {
return "";
}
+string StringifySyntax(FileDescriptor::Syntax syntax) {
+ switch (syntax) {
+ case FileDescriptor::SYNTAX_PROTO2:
+ return "proto2";
+ case FileDescriptor::SYNTAX_PROTO3:
+ return "proto3";
+ case FileDescriptor::SYNTAX_UNKNOWN:
+ default:
+ GOOGLE_LOG(FATAL) << "Unsupported syntax; this generator only supports proto2 "
+ "and proto3 syntax.";
+ return "";
+ }
+}
} // namespace
@@ -367,10 +380,12 @@ void Generator::PrintFileDescriptor() const {
m["descriptor_name"] = kDescriptorKey;
m["name"] = file_->name();
m["package"] = file_->package();
+ m["syntax"] = StringifySyntax(file_->syntax());
const char file_descriptor_template[] =
"$descriptor_name$ = _descriptor.FileDescriptor(\n"
" name='$name$',\n"
- " package='$package$',\n";
+ " package='$package$',\n"
+ " syntax='$syntax$',\n";
printer_->Print(m, file_descriptor_template);
printer_->Indent();
printer_->Print(
@@ -414,7 +429,7 @@ void Generator::PrintTopLevelEnums() const {
for (int j = 0; j < enum_descriptor.value_count(); ++j) {
const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(j);
top_level_enum_values.push_back(
- make_pair(value_descriptor.name(), value_descriptor.number()));
+ std::make_pair(value_descriptor.name(), value_descriptor.number()));
}
}
@@ -581,14 +596,15 @@ void Generator::PrintServiceDescriptor(
}
-void Generator::PrintDescriptorKeyAndModuleName(const ServiceDescriptor& descriptor) const {
+void Generator::PrintDescriptorKeyAndModuleName(
+ const ServiceDescriptor& descriptor) const {
printer_->Print(
"$descriptor_key$ = $descriptor_name$,\n",
"descriptor_key", kDescriptorKey,
"descriptor_name", ModuleLevelServiceDescriptorName(descriptor));
printer_->Print(
"__module__ = '$module_name$'\n",
- "module_name", ModuleName(file_->name()));
+ "module_name", ModuleName(file_->name()));
}
void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const {
@@ -664,10 +680,12 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const {
message_descriptor.options().SerializeToString(&options_string);
printer_->Print(
"options=$options_value$,\n"
- "is_extendable=$extendable$",
+ "is_extendable=$extendable$,\n"
+ "syntax='$syntax$'",
"options_value", OptionsValue("MessageOptions", options_string),
"extendable", message_descriptor.extension_range_count() > 0 ?
- "True" : "False");
+ "True" : "False",
+ "syntax", StringifySyntax(message_descriptor.file()->syntax()));
printer_->Print(",\n");
// Extension ranges
diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
index ee68ad72..2ddac601 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -127,7 +127,8 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
void PrintServiceDescriptor(const ServiceDescriptor& descriptor) const;
void PrintServiceClass(const ServiceDescriptor& descriptor) const;
void PrintServiceStub(const ServiceDescriptor& descriptor) const;
- void PrintDescriptorKeyAndModuleName(const ServiceDescriptor& descriptor) const ;
+ void PrintDescriptorKeyAndModuleName(
+ const ServiceDescriptor& descriptor) const ;
void PrintEnumValueDescriptor(const EnumValueDescriptor& descriptor) const;
string OptionsValue(const string& class_name,
diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_code.proto b/src/google/protobuf/compiler/ruby/ruby_generated_code.proto
new file mode 100644
index 00000000..42d82a6b
--- /dev/null
+++ b/src/google/protobuf/compiler/ruby/ruby_generated_code.proto
@@ -0,0 +1,67 @@
+syntax = "proto3";
+
+package A.B.C;
+
+message TestMessage {
+ int32 optional_int32 = 1;
+ int64 optional_int64 = 2;
+ uint32 optional_uint32 = 3;
+ uint64 optional_uint64 = 4;
+ bool optional_bool = 5;
+ double optional_double = 6;
+ float optional_float = 7;
+ string optional_string = 8;
+ bytes optional_bytes = 9;
+ TestEnum optional_enum = 10;
+ TestMessage optional_msg = 11;
+
+ repeated int32 repeated_int32 = 21;
+ repeated int64 repeated_int64 = 22;
+ repeated uint32 repeated_uint32 = 23;
+ repeated uint64 repeated_uint64 = 24;
+ repeated bool repeated_bool = 25;
+ repeated double repeated_double = 26;
+ repeated float repeated_float = 27;
+ repeated string repeated_string = 28;
+ repeated bytes repeated_bytes = 29;
+ repeated TestEnum repeated_enum = 30;
+ repeated TestMessage repeated_msg = 31;
+
+ oneof my_oneof {
+ int32 oneof_int32 = 41;
+ int64 oneof_int64 = 42;
+ uint32 oneof_uint32 = 43;
+ uint64 oneof_uint64 = 44;
+ bool oneof_bool = 45;
+ double oneof_double = 46;
+ float oneof_float = 47;
+ string oneof_string = 48;
+ bytes oneof_bytes = 49;
+ TestEnum oneof_enum = 50;
+ TestMessage oneof_msg = 51;
+ }
+
+ map<int32, string> map_int32_string = 61;
+ map<int64, string> map_int64_string = 62;
+ map<uint32, string> map_uint32_string = 63;
+ map<uint64, string> map_uint64_string = 64;
+ map<bool, string> map_bool_string = 65;
+ map<string, string> map_string_string = 66;
+ map<string, TestMessage> map_string_msg = 67;
+ map<string, TestEnum> map_string_enum = 68;
+ map<string, int32> map_string_int32 = 69;
+ map<string, bool> map_string_bool = 70;
+
+ message NestedMessage {
+ int32 foo = 1;
+ }
+
+ NestedMessage nested_message = 80;
+}
+
+enum TestEnum {
+ Default = 0;
+ A = 1;
+ B = 2;
+ C = 3;
+}
diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_code.rb b/src/google/protobuf/compiler/ruby/ruby_generated_code.rb
new file mode 100644
index 00000000..49b23fbe
--- /dev/null
+++ b/src/google/protobuf/compiler/ruby/ruby_generated_code.rb
@@ -0,0 +1,74 @@
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: ruby_generated_code.proto
+
+require 'google/protobuf'
+
+Google::Protobuf::DescriptorPool.generated_pool.build do
+ add_message "A.B.C.TestMessage" do
+ optional :optional_int32, :int32, 1
+ optional :optional_int64, :int64, 2
+ optional :optional_uint32, :uint32, 3
+ optional :optional_uint64, :uint64, 4
+ optional :optional_bool, :bool, 5
+ optional :optional_double, :double, 6
+ optional :optional_float, :float, 7
+ optional :optional_string, :string, 8
+ optional :optional_bytes, :bytes, 9
+ optional :optional_enum, :enum, 10, "A.B.C.TestEnum"
+ optional :optional_msg, :message, 11, "A.B.C.TestMessage"
+ repeated :repeated_int32, :int32, 21
+ repeated :repeated_int64, :int64, 22
+ repeated :repeated_uint32, :uint32, 23
+ repeated :repeated_uint64, :uint64, 24
+ repeated :repeated_bool, :bool, 25
+ repeated :repeated_double, :double, 26
+ repeated :repeated_float, :float, 27
+ repeated :repeated_string, :string, 28
+ repeated :repeated_bytes, :bytes, 29
+ repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum"
+ repeated :repeated_msg, :message, 31, "A.B.C.TestMessage"
+ map :map_int32_string, :int32, :string, 61
+ map :map_int64_string, :int64, :string, 62
+ map :map_uint32_string, :uint32, :string, 63
+ map :map_uint64_string, :uint64, :string, 64
+ map :map_bool_string, :bool, :string, 65
+ map :map_string_string, :string, :string, 66
+ map :map_string_msg, :string, :message, 67, "A.B.C.TestMessage"
+ map :map_string_enum, :string, :enum, 68, "A.B.C.TestEnum"
+ map :map_string_int32, :string, :int32, 69
+ map :map_string_bool, :string, :bool, 70
+ optional :nested_message, :message, 80, "A.B.C.TestMessage.NestedMessage"
+ oneof :my_oneof do
+ optional :oneof_int32, :int32, 41
+ optional :oneof_int64, :int64, 42
+ optional :oneof_uint32, :uint32, 43
+ optional :oneof_uint64, :uint64, 44
+ optional :oneof_bool, :bool, 45
+ optional :oneof_double, :double, 46
+ optional :oneof_float, :float, 47
+ optional :oneof_string, :string, 48
+ optional :oneof_bytes, :bytes, 49
+ optional :oneof_enum, :enum, 50, "A.B.C.TestEnum"
+ optional :oneof_msg, :message, 51, "A.B.C.TestMessage"
+ end
+ end
+ add_message "A.B.C.TestMessage.NestedMessage" do
+ optional :foo, :int32, 1
+ end
+ add_enum "A.B.C.TestEnum" do
+ value :Default, 0
+ value :A, 1
+ value :B, 2
+ value :C, 3
+ end
+end
+
+module A
+ module B
+ module C
+ TestMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage").msgclass
+ TestMessage::NestedMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.NestedMessage").msgclass
+ TestEnum = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestEnum").enummodule
+ end
+ end
+end
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc
index c5687903..9692f1bf 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator.cc
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc
@@ -47,7 +47,7 @@ namespace compiler {
namespace ruby {
// Forward decls.
-std::string IntToString(uint32_t value);
+std::string IntToString(int32 value);
std::string StripDotProto(const std::string& proto_file);
std::string LabelForField(google::protobuf::FieldDescriptor* field);
std::string TypeName(google::protobuf::FieldDescriptor* field);
@@ -64,7 +64,7 @@ void GenerateEnumAssignment(
const google::protobuf::EnumDescriptor* en,
google::protobuf::io::Printer* printer);
-std::string IntToString(uint32_t value) {
+std::string IntToString(int32 value) {
std::ostringstream os;
os << value;
return os.str();
@@ -85,30 +85,58 @@ std::string LabelForField(const google::protobuf::FieldDescriptor* field) {
}
std::string TypeName(const google::protobuf::FieldDescriptor* field) {
- switch (field->cpp_type()) {
- case FieldDescriptor::CPPTYPE_INT32: return "int32";
- case FieldDescriptor::CPPTYPE_INT64: return "int64";
- case FieldDescriptor::CPPTYPE_UINT32: return "uint32";
- case FieldDescriptor::CPPTYPE_UINT64: return "uint64";
- case FieldDescriptor::CPPTYPE_DOUBLE: return "double";
- case FieldDescriptor::CPPTYPE_FLOAT: return "float";
- case FieldDescriptor::CPPTYPE_BOOL: return "bool";
- case FieldDescriptor::CPPTYPE_ENUM: return "enum";
- case FieldDescriptor::CPPTYPE_STRING: return "string";
- case FieldDescriptor::CPPTYPE_MESSAGE: return "message";
+ switch (field->type()) {
+ case FieldDescriptor::TYPE_INT32: return "int32";
+ case FieldDescriptor::TYPE_INT64: return "int64";
+ case FieldDescriptor::TYPE_UINT32: return "uint32";
+ case FieldDescriptor::TYPE_UINT64: return "uint64";
+ case FieldDescriptor::TYPE_SINT32: return "sint32";
+ case FieldDescriptor::TYPE_SINT64: return "sint64";
+ case FieldDescriptor::TYPE_FIXED32: return "fixed32";
+ case FieldDescriptor::TYPE_FIXED64: return "fixed64";
+ case FieldDescriptor::TYPE_SFIXED32: return "sfixed32";
+ case FieldDescriptor::TYPE_SFIXED64: return "sfixed64";
+ case FieldDescriptor::TYPE_DOUBLE: return "double";
+ case FieldDescriptor::TYPE_FLOAT: return "float";
+ case FieldDescriptor::TYPE_BOOL: return "bool";
+ case FieldDescriptor::TYPE_ENUM: return "enum";
+ case FieldDescriptor::TYPE_STRING: return "string";
+ case FieldDescriptor::TYPE_BYTES: return "bytes";
+ case FieldDescriptor::TYPE_MESSAGE: return "message";
+ case FieldDescriptor::TYPE_GROUP: return "group";
default: assert(false); return "";
}
}
-void GenerateMessage(const google::protobuf::Descriptor* message,
- google::protobuf::io::Printer* printer) {
- printer->Print(
- "add_message \"$name$\" do\n",
- "name", message->full_name());
- printer->Indent();
+void GenerateField(const google::protobuf::FieldDescriptor* field,
+ google::protobuf::io::Printer* printer) {
+
+ if (field->is_map()) {
+ const FieldDescriptor* key_field =
+ field->message_type()->FindFieldByNumber(1);
+ const FieldDescriptor* value_field =
+ field->message_type()->FindFieldByNumber(2);
+
+ printer->Print(
+ "map :$name$, :$key_type$, :$value_type$, $number$",
+ "name", field->name(),
+ "key_type", TypeName(key_field),
+ "value_type", TypeName(value_field),
+ "number", IntToString(field->number()));
+
+ if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ printer->Print(
+ ", \"$subtype$\"\n",
+ "subtype", value_field->message_type()->full_name());
+ } else if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ printer->Print(
+ ", \"$subtype$\"\n",
+ "subtype", value_field->enum_type()->full_name());
+ } else {
+ printer->Print("\n");
+ }
+ } else {
- for (int i = 0; i < message->field_count(); i++) {
- const FieldDescriptor* field = message->field(i);
printer->Print(
"$label$ :$name$, ",
"label", LabelForField(field),
@@ -117,6 +145,7 @@ void GenerateMessage(const google::protobuf::Descriptor* message,
":$type$, $number$",
"type", TypeName(field),
"number", IntToString(field->number()));
+
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
printer->Print(
", \"$subtype$\"\n",
@@ -129,6 +158,49 @@ void GenerateMessage(const google::protobuf::Descriptor* message,
printer->Print("\n");
}
}
+}
+
+void GenerateOneof(const google::protobuf::OneofDescriptor* oneof,
+ google::protobuf::io::Printer* printer) {
+ printer->Print(
+ "oneof :$name$ do\n",
+ "name", oneof->name());
+ printer->Indent();
+
+ for (int i = 0; i < oneof->field_count(); i++) {
+ const FieldDescriptor* field = oneof->field(i);
+ GenerateField(field, printer);
+ }
+
+ printer->Outdent();
+ printer->Print("end\n");
+}
+
+void GenerateMessage(const google::protobuf::Descriptor* message,
+ google::protobuf::io::Printer* printer) {
+
+ // Don't generate MapEntry messages -- we use the Ruby extension's native
+ // support for map fields instead.
+ if (message->options().map_entry()) {
+ return;
+ }
+
+ printer->Print(
+ "add_message \"$name$\" do\n",
+ "name", message->full_name());
+ printer->Indent();
+
+ for (int i = 0; i < message->field_count(); i++) {
+ const FieldDescriptor* field = message->field(i);
+ if (!field->containing_oneof()) {
+ GenerateField(field, printer);
+ }
+ }
+
+ for (int i = 0; i < message->oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof = message->oneof_decl(i);
+ GenerateOneof(oneof, printer);
+ }
printer->Outdent();
printer->Print("end\n");
@@ -185,6 +257,13 @@ void GenerateMessageAssignment(
const std::string& prefix,
const google::protobuf::Descriptor* message,
google::protobuf::io::Printer* printer) {
+
+ // Don't generate MapEntry messages -- we use the Ruby extension's native
+ // support for map fields instead.
+ if (message->options().map_entry()) {
+ return;
+ }
+
printer->Print(
"$prefix$$name$ = ",
"prefix", prefix,
@@ -307,7 +386,8 @@ bool Generator::Generate(
std::string filename =
StripDotProto(file->name()) + ".rb";
- scoped_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(filename));
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(filename));
io::Printer printer(output.get(), '$');
GenerateFile(file, &printer);
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.h b/src/google/protobuf/compiler/ruby/ruby_generator.h
index 48dbefd1..75555c31 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator.h
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.h
@@ -40,7 +40,8 @@ namespace protobuf {
namespace compiler {
namespace ruby {
-class Generator : public google::protobuf::compiler::CodeGenerator {
+class LIBPROTOC_EXPORT Generator
+ : public google::protobuf::compiler::CodeGenerator {
virtual bool Generate(
const FileDescriptor* file,
const string& parameter,
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
new file mode 100644
index 00000000..1b04cb32
--- /dev/null
+++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
@@ -0,0 +1,123 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <memory>
+
+#include <google/protobuf/compiler/ruby/ruby_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/file.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace ruby {
+namespace {
+
+string FindRubyTestDir(const string& file) {
+ // Inspired by TestSourceDir() in src/google/protobuf/testing/googletest.cc.
+#ifndef GOOGLE_THIRD_PARTY_PROTOBUF
+ string prefix = ".";
+ while (!File::Exists(prefix + "/src/google/protobuf/compiler/ruby" + file)) {
+ if (!File::Exists(prefix)) {
+ GOOGLE_LOG(FATAL)
+ << "Could not find Ruby test directory. Please run tests from "
+ "somewhere within the protobuf source package.";
+ }
+ prefix += "/..";
+ }
+ return prefix + "/src/google/protobuf/compiler/ruby";
+#else
+ return "third_party/protobuf/src/google/protobuf/compiler/ruby";
+#endif // GOOGLE_THIRD_PARTY_PROTOBUF
+}
+
+// This test is a simple golden-file test over the output of the Ruby code
+// generator. When we make changes to the Ruby extension and alter the Ruby code
+// generator to use those changes, we should (i) manually test the output of the
+// code generator with the extension, and (ii) update the golden output above.
+// Some day, we may integrate build systems between protoc and the language
+// extensions to the point where we can do this test in a more automated way.
+
+TEST(RubyGeneratorTest, GeneratorTest) {
+ string ruby_tests = FindRubyTestDir("/ruby_generated_code.proto");
+
+ google::protobuf::compiler::CommandLineInterface cli;
+ cli.SetInputsAreProtoPathRelative(true);
+
+ ruby::Generator ruby_generator;
+ cli.RegisterGenerator("--ruby_out", &ruby_generator, "");
+
+ // Copy generated_code.proto to the temporary test directory.
+ string test_input;
+ GOOGLE_CHECK_OK(File::GetContents(
+ ruby_tests + "/ruby_generated_code.proto",
+ &test_input,
+ true));
+ GOOGLE_CHECK_OK(File::SetContents(
+ TestTempDir() + "/ruby_generated_code.proto",
+ test_input,
+ true));
+
+ // Invoke the proto compiler (we will be inside TestTempDir() at this point).
+ string ruby_out = "--ruby_out=" + TestTempDir();
+ string proto_path = "--proto_path=" + TestTempDir();
+ const char* argv[] = {
+ "protoc",
+ ruby_out.c_str(),
+ proto_path.c_str(),
+ "ruby_generated_code.proto",
+ };
+
+ EXPECT_EQ(0, cli.Run(4, argv));
+
+ // Load the generated output and compare to the expected result.
+ string output;
+ GOOGLE_CHECK_OK(File::GetContents(
+ TestTempDir() + "/ruby_generated_code.rb",
+ &output,
+ true));
+ string expected_output;
+ GOOGLE_CHECK_OK(File::GetContents(
+ ruby_tests + "/ruby_generated_code.rb",
+ &expected_output,
+ true));
+ EXPECT_EQ(expected_output, output);
+}
+
+} // namespace
+} // namespace ruby
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc
index 61ae4381..a3cff1f8 100644
--- a/src/google/protobuf/compiler/subprocess.cc
+++ b/src/google/protobuf/compiler/subprocess.cc
@@ -171,7 +171,7 @@ bool Subprocess::Communicate(const Message& input, Message* output,
DWORD wait_result =
WaitForMultipleObjects(handle_count, handles, FALSE, INFINITE);
- HANDLE signaled_handle;
+ HANDLE signaled_handle = NULL;
if (wait_result >= WAIT_OBJECT_0 &&
wait_result < WAIT_OBJECT_0 + handle_count) {
signaled_handle = handles[wait_result - WAIT_OBJECT_0];
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index b8dd198d..2855c377 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -783,7 +783,7 @@ inline const FileDescriptor* DescriptorPool::Tables::FindFile(
inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber(
const Descriptor* parent, int number) const {
- return FindPtrOrNull(fields_by_number_, make_pair(parent, number));
+ return FindPtrOrNull(fields_by_number_, std::make_pair(parent, number));
}
inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName(
@@ -800,7 +800,7 @@ inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName(
inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber(
const EnumDescriptor* parent, int number) const {
- return FindPtrOrNull(enum_values_by_number_, make_pair(parent, number));
+ return FindPtrOrNull(enum_values_by_number_, std::make_pair(parent, number));
}
inline const EnumValueDescriptor*
@@ -808,8 +808,8 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
const EnumDescriptor* parent, int number) const {
// First try, with map of compiled-in values.
{
- const EnumValueDescriptor* desc = FindPtrOrNull(
- enum_values_by_number_, make_pair(parent, number));
+ const EnumValueDescriptor* desc =
+ FindPtrOrNull(enum_values_by_number_, std::make_pair(parent, number));
if (desc != NULL) {
return desc;
}
@@ -818,7 +818,7 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
{
ReaderMutexLock l(&unknown_enum_values_mu_);
const EnumValueDescriptor* desc = FindPtrOrNull(
- unknown_enum_values_by_number_, make_pair(parent, number));
+ unknown_enum_values_by_number_, std::make_pair(parent, number));
if (desc != NULL) {
return desc;
}
@@ -828,7 +828,7 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
{
WriterMutexLock l(&unknown_enum_values_mu_);
const EnumValueDescriptor* desc = FindPtrOrNull(
- unknown_enum_values_by_number_, make_pair(parent, number));
+ unknown_enum_values_by_number_, std::make_pair(parent, number));
if (desc != NULL) {
return desc;
}
@@ -850,8 +850,7 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
result->type_ = parent;
result->options_ = &EnumValueOptions::default_instance();
InsertIfNotPresent(&unknown_enum_values_by_number_,
- make_pair(parent, number),
- result);
+ std::make_pair(parent, number), result);
return result;
}
}
@@ -859,13 +858,13 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
inline const FieldDescriptor* DescriptorPool::Tables::FindExtension(
const Descriptor* extendee, int number) {
- return FindPtrOrNull(extensions_, make_pair(extendee, number));
+ return FindPtrOrNull(extensions_, std::make_pair(extendee, number));
}
inline void DescriptorPool::Tables::FindAllExtensions(
const Descriptor* extendee, vector<const FieldDescriptor*>* out) const {
ExtensionsGroupedByDescriptorMap::const_iterator it =
- extensions_.lower_bound(make_pair(extendee, 0));
+ extensions_.lower_bound(std::make_pair(extendee, 0));
for (; it != extensions_.end() && it->first.first == extendee; ++it) {
out->push_back(it->second);
}
@@ -993,7 +992,7 @@ void FileDescriptorTables::BuildLocationsByPath(
const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation(
const vector<int>& path, const SourceCodeInfo* info) const {
pair<const FileDescriptorTables*, const SourceCodeInfo*> p(
- make_pair(this, info));
+ std::make_pair(this, info));
locations_by_path_once_.Init(&FileDescriptorTables::BuildLocationsByPath, &p);
return FindPtrOrNull(locations_by_path_, Join(path, ","));
}
@@ -1519,6 +1518,18 @@ Descriptor::FindExtensionRangeContainingNumber(int number) const {
return NULL;
}
+const Descriptor::ReservedRange*
+Descriptor::FindReservedRangeContainingNumber(int number) const {
+ // TODO(chrisn): Consider a non-linear search.
+ for (int i = 0; i < reserved_range_count(); i++) {
+ if (number >= reserved_range(i)->start &&
+ number < reserved_range(i)->end) {
+ return reserved_range(i);
+ }
+ }
+ return NULL;
+}
+
// -------------------------------------------------------------------
bool DescriptorPool::TryFindFileInFallbackDatabase(const string& name) const {
@@ -1742,6 +1753,14 @@ void Descriptor::CopyTo(DescriptorProto* proto) const {
for (int i = 0; i < extension_count(); i++) {
extension(i)->CopyTo(proto->add_extension());
}
+ for (int i = 0; i < reserved_range_count(); i++) {
+ DescriptorProto::ReservedRange* range = proto->add_reserved_range();
+ range->set_start(reserved_range(i)->start);
+ range->set_end(reserved_range(i)->end);
+ }
+ for (int i = 0; i < reserved_name_count(); i++) {
+ proto->add_reserved_name(reserved_name(i));
+ }
if (&options() != &MessageOptions::default_instance()) {
proto->mutable_options()->CopyFrom(options());
@@ -1929,9 +1948,9 @@ bool FormatLineOptions(int depth, const Message &options, string *output) {
return !all_options.empty();
}
-template<typename DescType>
class SourceLocationCommentPrinter {
public:
+ template<typename DescType>
SourceLocationCommentPrinter(const DescType* desc,
const string& prefix,
const DebugStringOptions& options)
@@ -1941,9 +1960,27 @@ class SourceLocationCommentPrinter {
have_source_loc_ = options.include_comments &&
desc->GetSourceLocation(&source_loc_);
}
+ SourceLocationCommentPrinter(const FileDescriptor* file,
+ const vector<int>& path,
+ const string& prefix,
+ const DebugStringOptions& options)
+ : options_(options), prefix_(prefix) {
+ // Perform the SourceLocation lookup only if we're including user comments,
+ // because the lookup is fairly expensive.
+ have_source_loc_ = options.include_comments &&
+ file->GetSourceLocation(path, &source_loc_);
+ }
void AddPreComment(string* output) {
- if (have_source_loc_ && source_loc_.leading_comments.size() > 0) {
- *output += FormatComment(source_loc_.leading_comments);
+ if (have_source_loc_) {
+ // Detached leading comments.
+ for (int i = 0 ; i < source_loc_.leading_detached_comments.size(); ++i) {
+ *output += FormatComment(source_loc_.leading_detached_comments[i]);
+ *output += "\n";
+ }
+ // Attached leading comments.
+ if (!source_loc_.leading_comments.empty()) {
+ *output += FormatComment(source_loc_.leading_comments);
+ }
}
}
void AddPostComment(string* output) {
@@ -1967,7 +2004,6 @@ class SourceLocationCommentPrinter {
}
private:
- const DescType* desc_;
bool have_source_loc_;
SourceLocation source_loc_;
DebugStringOptions options_;
@@ -1984,10 +2020,18 @@ string FileDescriptor::DebugString() const {
string FileDescriptor::DebugStringWithOptions(
const DebugStringOptions& debug_string_options) const {
string contents;
- strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n",
- SyntaxName(syntax()));
+ {
+ vector<int> path;
+ path.push_back(FileDescriptorProto::kSyntaxFieldNumber);
+ SourceLocationCommentPrinter syntax_comment(
+ this, path, "", debug_string_options);
+ syntax_comment.AddPreComment(&contents);
+ strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n",
+ SyntaxName(syntax()));
+ syntax_comment.AddPostComment(&contents);
+ }
- SourceLocationCommentPrinter<FileDescriptor>
+ SourceLocationCommentPrinter
comment_printer(this, "", debug_string_options);
comment_printer.AddPreComment(&contents);
@@ -2012,7 +2056,13 @@ string FileDescriptor::DebugStringWithOptions(
}
if (!package().empty()) {
+ vector<int> path;
+ path.push_back(FileDescriptorProto::kPackageFieldNumber);
+ SourceLocationCommentPrinter package_comment(
+ this, path, "", debug_string_options);
+ package_comment.AddPreComment(&contents);
strings::SubstituteAndAppend(&contents, "package $0;\n\n", package());
+ package_comment.AddPostComment(&contents);
}
if (FormatLineOptions(0, options(), &contents)) {
@@ -2087,7 +2137,7 @@ void Descriptor::DebugString(int depth, string *contents,
string prefix(depth * 2, ' ');
++depth;
- SourceLocationCommentPrinter<Descriptor>
+ SourceLocationCommentPrinter
comment_printer(this, prefix, debug_string_options);
comment_printer.AddPreComment(contents);
@@ -2156,6 +2206,29 @@ void Descriptor::DebugString(int depth, string *contents,
if (extension_count() > 0)
strings::SubstituteAndAppend(contents, "$0 }\n", prefix);
+ if (reserved_range_count() > 0) {
+ strings::SubstituteAndAppend(contents, "$0 reserved ", prefix);
+ for (int i = 0; i < reserved_range_count(); i++) {
+ const Descriptor::ReservedRange* range = reserved_range(i);
+ if (range->end == range->start + 1) {
+ strings::SubstituteAndAppend(contents, "$0, ", range->start);
+ } else {
+ strings::SubstituteAndAppend(contents, "$0 to $1, ",
+ range->start, range->end - 1);
+ }
+ }
+ contents->replace(contents->size() - 2, 2, ";\n");
+ }
+
+ if (reserved_name_count() > 0) {
+ strings::SubstituteAndAppend(contents, "$0 reserved ", prefix);
+ for (int i = 0; i < reserved_name_count(); i++) {
+ strings::SubstituteAndAppend(contents, "\"$0\", ",
+ CEscape(reserved_name(i)));
+ }
+ contents->replace(contents->size() - 2, 2, ";\n");
+ }
+
strings::SubstituteAndAppend(contents, "$0}\n", prefix);
comment_printer.AddPostComment(contents);
}
@@ -2217,7 +2290,7 @@ void FieldDescriptor::DebugString(int depth,
label.push_back(' ');
}
- SourceLocationCommentPrinter<FieldDescriptor>
+ SourceLocationCommentPrinter
comment_printer(this, prefix, debug_string_options);
comment_printer.AddPreComment(contents);
@@ -2248,8 +2321,12 @@ void FieldDescriptor::DebugString(int depth,
}
if (type() == TYPE_GROUP) {
- message_type()->DebugString(depth, contents, debug_string_options,
- /* include_opening_clause */ false);
+ if (debug_string_options.elide_group_body) {
+ contents->append(" { ... };\n");
+ } else {
+ message_type()->DebugString(depth, contents, debug_string_options,
+ /* include_opening_clause */ false);
+ }
} else {
contents->append(";\n");
}
@@ -2274,16 +2351,20 @@ void OneofDescriptor::DebugString(int depth, string* contents,
debug_string_options) const {
string prefix(depth * 2, ' ');
++depth;
- SourceLocationCommentPrinter<OneofDescriptor>
+ SourceLocationCommentPrinter
comment_printer(this, prefix, debug_string_options);
comment_printer.AddPreComment(contents);
strings::SubstituteAndAppend(
- contents, "$0 oneof $1 {\n", prefix, name());
- for (int i = 0; i < field_count(); i++) {
- field(i)->DebugString(depth, FieldDescriptor::OMIT_LABEL, contents,
- debug_string_options);
+ contents, "$0 oneof $1 {", prefix, name());
+ if (debug_string_options.elide_oneof_body) {
+ contents->append(" ... }\n");
+ } else {
+ for (int i = 0; i < field_count(); i++) {
+ field(i)->DebugString(depth, FieldDescriptor::OMIT_LABEL, contents,
+ debug_string_options);
+ }
+ strings::SubstituteAndAppend(contents, "$0}\n", prefix);
}
- strings::SubstituteAndAppend(contents, "$0}\n", prefix);
comment_printer.AddPostComment(contents);
}
@@ -2305,7 +2386,7 @@ void EnumDescriptor::DebugString(int depth, string *contents,
string prefix(depth * 2, ' ');
++depth;
- SourceLocationCommentPrinter<EnumDescriptor>
+ SourceLocationCommentPrinter
comment_printer(this, prefix, debug_string_options);
comment_printer.AddPreComment(contents);
@@ -2339,7 +2420,7 @@ void EnumValueDescriptor::DebugString(int depth, string *contents,
debug_string_options) const {
string prefix(depth * 2, ' ');
- SourceLocationCommentPrinter<EnumValueDescriptor>
+ SourceLocationCommentPrinter
comment_printer(this, prefix, debug_string_options);
comment_printer.AddPreComment(contents);
@@ -2370,7 +2451,7 @@ string ServiceDescriptor::DebugStringWithOptions(
void ServiceDescriptor::DebugString(string *contents,
const DebugStringOptions&
debug_string_options) const {
- SourceLocationCommentPrinter<ServiceDescriptor>
+ SourceLocationCommentPrinter
comment_printer(this, /* prefix */ "", debug_string_options);
comment_printer.AddPreComment(contents);
@@ -2405,7 +2486,7 @@ void MethodDescriptor::DebugString(int depth, string *contents,
string prefix(depth * 2, ' ');
++depth;
- SourceLocationCommentPrinter<MethodDescriptor>
+ SourceLocationCommentPrinter
comment_printer(this, prefix, debug_string_options);
comment_printer.AddPreComment(contents);
@@ -2445,6 +2526,9 @@ bool FileDescriptor::GetSourceLocation(const vector<int>& path,
out_location->leading_comments = loc->leading_comments();
out_location->trailing_comments = loc->trailing_comments();
+ out_location->leading_detached_comments.assign(
+ loc->leading_detached_comments().begin(),
+ loc->leading_detached_comments().end());
return true;
}
}
@@ -2458,7 +2542,12 @@ bool FileDescriptor::GetSourceLocation(SourceLocation* out_location) const {
}
bool FieldDescriptor::is_packed() const {
- return is_packable() && (options_ != NULL) && options_->packed();
+ if (!is_packable()) return false;
+ if (file_->syntax() == FileDescriptor::SYNTAX_PROTO2) {
+ return (options_ != NULL) && options_->packed();
+ } else {
+ return options_ == NULL || !options_->has_packed() || options_->packed();
+ }
}
bool Descriptor::GetSourceLocation(SourceLocation* out_location) const {
@@ -2571,7 +2660,7 @@ void MethodDescriptor::GetLocationPath(vector<int>* output) const {
namespace {
// Represents an options message to interpret. Extension names in the option
-// name are respolved relative to name_scope. element_name and orig_opt are
+// name are resolved relative to name_scope. element_name and orig_opt are
// used only for error reporting (since the parser records locations against
// pointers in the original options, not the mutable copy). The Message must be
// one of the Options messages in descriptor.proto.
@@ -2797,6 +2886,9 @@ class DescriptorBuilder {
void BuildExtensionRange(const DescriptorProto::ExtensionRange& proto,
const Descriptor* parent,
Descriptor::ExtensionRange* result);
+ void BuildReservedRange(const DescriptorProto::ReservedRange& proto,
+ const Descriptor* parent,
+ Descriptor::ReservedRange* result);
void BuildOneof(const OneofDescriptorProto& proto,
Descriptor* parent,
OneofDescriptor* result);
@@ -3697,7 +3789,6 @@ const FileDescriptor* DescriptorBuilder::BuildFile(
"Unrecognized syntax: " + proto.syntax());
}
-
result->name_ = tables_->AllocateString(proto.name());
if (proto.has_package()) {
result->package_ = tables_->AllocateString(proto.package());
@@ -3888,6 +3979,17 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
BUILD_ARRAY(proto, result, enum_type , BuildEnum , result);
BUILD_ARRAY(proto, result, extension_range, BuildExtensionRange, result);
BUILD_ARRAY(proto, result, extension , BuildExtension , result);
+ BUILD_ARRAY(proto, result, reserved_range , BuildReservedRange , result);
+
+ // Copy reserved names.
+ int reserved_name_count = proto.reserved_name_size();
+ result->reserved_name_count_ = reserved_name_count;
+ result->reserved_names_ =
+ tables_->AllocateArray<const string*>(reserved_name_count);
+ for (int i = 0; i < reserved_name_count; ++i) {
+ result->reserved_names_[i] =
+ tables_->AllocateString(proto.reserved_name(i));
+ }
// Copy options.
if (!proto.has_options()) {
@@ -3899,7 +4001,34 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
AddSymbol(result->full_name(), parent, result->name(),
proto, Symbol(result));
- // Check that no fields have numbers in extension ranges.
+ for (int i = 0; i < proto.reserved_range_size(); i++) {
+ const DescriptorProto_ReservedRange& range1 = proto.reserved_range(i);
+ for (int j = i + 1; j < proto.reserved_range_size(); j++) {
+ const DescriptorProto_ReservedRange& range2 = proto.reserved_range(j);
+ if (range1.end() > range2.start() && range2.end() > range1.start()) {
+ AddError(result->full_name(), proto.reserved_range(i),
+ DescriptorPool::ErrorCollector::NUMBER,
+ strings::Substitute("Reserved range $0 to $1 overlaps with "
+ "already-defined range $2 to $3.",
+ range2.start(), range2.end() - 1,
+ range1.start(), range1.end() - 1));
+ }
+ }
+ }
+
+ hash_set<string> reserved_name_set;
+ for (int i = 0; i < proto.reserved_name_size(); i++) {
+ const string& name = proto.reserved_name(i);
+ if (reserved_name_set.find(name) == reserved_name_set.end()) {
+ reserved_name_set.insert(name);
+ } else {
+ AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
+ strings::Substitute(
+ "Field name \"$0\" is reserved multiple times.",
+ name));
+ }
+ }
+
for (int i = 0; i < result->field_count(); i++) {
const FieldDescriptor* field = result->field(i);
for (int j = 0; j < result->extension_range_count(); j++) {
@@ -3913,11 +4042,39 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
field->name(), field->number()));
}
}
+ for (int j = 0; j < result->reserved_range_count(); j++) {
+ const Descriptor::ReservedRange* range = result->reserved_range(j);
+ if (range->start <= field->number() && field->number() < range->end) {
+ AddError(field->full_name(), proto.reserved_range(j),
+ DescriptorPool::ErrorCollector::NUMBER,
+ strings::Substitute(
+ "Field \"$0\" uses reserved number $1.",
+ field->name(), field->number()));
+ }
+ }
+ if (reserved_name_set.find(field->name()) != reserved_name_set.end()) {
+ AddError(field->full_name(), proto.field(i),
+ DescriptorPool::ErrorCollector::NAME,
+ strings::Substitute(
+ "Field name \"$0\" is reserved.", field->name()));
+ }
}
- // Check that extension ranges don't overlap.
+ // Check that extension ranges don't overlap and don't include
+ // reserved field numbers.
for (int i = 0; i < result->extension_range_count(); i++) {
const Descriptor::ExtensionRange* range1 = result->extension_range(i);
+ for (int j = 0; j < result->reserved_range_count(); j++) {
+ const Descriptor::ReservedRange* range2 = result->reserved_range(j);
+ if (range1->end > range2->start && range2->end > range1->start) {
+ AddError(result->full_name(), proto.extension_range(j),
+ DescriptorPool::ErrorCollector::NUMBER,
+ strings::Substitute("Extension range $0 to $1 overlaps with "
+ "reserved range $2 to $3.",
+ range1->start, range1->end - 1,
+ range2->start, range2->end - 1));
+ }
+ }
for (int j = i + 1; j < result->extension_range_count(); j++) {
const Descriptor::ExtensionRange* range2 = result->extension_range(j);
if (range1->end > range2->start && range2->end > range1->start) {
@@ -4230,6 +4387,19 @@ void DescriptorBuilder::BuildExtensionRange(
}
}
+void DescriptorBuilder::BuildReservedRange(
+ const DescriptorProto::ReservedRange& proto,
+ const Descriptor* parent,
+ Descriptor::ReservedRange* result) {
+ result->start = proto.start();
+ result->end = proto.end();
+ if (result->start <= 0) {
+ AddError(parent->full_name(), proto,
+ DescriptorPool::ErrorCollector::NUMBER,
+ "Reserved numbers must be positive integers.");
+ }
+}
+
void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto,
Descriptor* parent,
OneofDescriptor* result) {
@@ -4471,6 +4641,23 @@ void DescriptorBuilder::CrossLinkMessage(
for (int i = 0; i < message->field_count(); i++) {
const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
if (oneof_decl != NULL) {
+ // Make sure fields belonging to the same oneof are defined consecutively.
+ // This enables optimizations in codegens and reflection libraries to
+ // skip fields in the oneof group, as only one of the field can be set.
+ // Note that field_count() returns how many fields in this oneof we have
+ // seen so far. field_count() > 0 guarantees that i > 0, so field(i-1) is
+ // safe.
+ if (oneof_decl->field_count() > 0 &&
+ message->field(i - 1)->containing_oneof() != oneof_decl) {
+ AddWarning(
+ message->full_name() + "." + message->field(i - 1)->name(),
+ proto.field(i - 1), DescriptorPool::ErrorCollector::OTHER,
+ strings::Substitute(
+ "Fields in the same oneof must be defined consecutively. "
+ "\"$0\" cannot be defined before the completion of the "
+ "\"$1\" oneof definition.",
+ message->field(i - 1)->name(), oneof_decl->name()));
+ }
// Must go through oneof_decls_ array to get a non-const version of the
// OneofDescriptor.
++message->oneof_decls_[oneof_decl->index()].field_count_;
@@ -4901,6 +5088,12 @@ void DescriptorBuilder::ValidateProto3Field(
field->containing_type()->full_name() +
"\" which is a proto3 message type.");
}
+ bool allow_groups = false;
+ if (field->type() == FieldDescriptor::TYPE_GROUP && !allow_groups) {
+ AddError(field->full_name(), proto,
+ DescriptorPool::ErrorCollector::TYPE,
+ "Groups are not supported in proto3 syntax.");
+ }
}
void DescriptorBuilder::ValidateProto3Enum(
@@ -5110,7 +5303,7 @@ bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field,
case FieldDescriptor::TYPE_SFIXED64:
// Legal cases
break;
- // Do not add a default, so that the compiler will complian when new types
+ // Do not add a default, so that the compiler will complain when new types
// are added.
}
@@ -5123,7 +5316,7 @@ void DescriptorBuilder::DetectMapConflicts(const Descriptor* message,
for (int i = 0; i < message->nested_type_count(); ++i) {
const Descriptor* nested = message->nested_type(i);
pair<map<string, const Descriptor*>::iterator, bool> result =
- seen_types.insert(make_pair(nested->name(), nested));
+ seen_types.insert(std::make_pair(nested->name(), nested));
if (!result.second) {
if (result.first->second->options().map_entry() ||
nested->options().map_entry()) {
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 52df47f3..ca87d634 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -59,6 +59,10 @@
#include <vector>
#include <google/protobuf/stubs/common.h>
+// TYPE_BOOL is defined in the MacOS's ConditionalMacros.h.
+#ifdef TYPE_BOOL
+#undef TYPE_BOOL
+#endif // TYPE_BOOL
namespace google {
namespace protobuf {
@@ -117,8 +121,10 @@ struct SourceLocation {
int end_column;
// Doc comments found at the source location.
+ // See the comments in SourceCodeInfo.Location (descriptor.proto) for details.
string leading_comments;
string trailing_comments;
+ vector<string> leading_detached_comments;
};
// Options when generating machine-parsable output from a descriptor with
@@ -129,10 +135,14 @@ struct DebugStringOptions {
// example, the C++ code generation for fields in the proto compiler) rely on
// DebugString() output being unobstructed by user comments.
bool include_comments;
+ // If true, elide the braced body in the debug string.
+ bool elide_group_body;
+ bool elide_oneof_body;
DebugStringOptions()
- : include_comments(false)
- {}
+ : include_comments(false),
+ elide_group_body(false),
+ elide_oneof_body(false) {}
};
// Describes a type of protocol message, or a particular group within a
@@ -292,6 +302,36 @@ class LIBPROTOBUF_EXPORT Descriptor {
// this message type's scope.
const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const;
+ // Reserved fields -------------------------------------------------
+
+ // A range of reserved field numbers.
+ struct ReservedRange {
+ int start; // inclusive
+ int end; // exclusive
+ };
+
+ // The number of reserved ranges in this message type.
+ int reserved_range_count() const;
+ // Gets an reserved range by index, where 0 <= index <
+ // reserved_range_count(). These are returned in the order they were defined
+ // in the .proto file.
+ const ReservedRange* reserved_range(int index) const;
+
+ // Returns true if the number is in one of the reserved ranges.
+ bool IsReservedNumber(int number) const;
+
+ // Returns NULL if no reserved range contains the given number.
+ const ReservedRange* FindReservedRangeContainingNumber(int number) const;
+
+ // The number of reserved field names in this message type.
+ int reserved_name_count() const;
+
+ // Gets a reserved name by index, where 0 <= index < reserved_name_count().
+ const string& reserved_name(int index) const;
+
+ // Returns true if the field name is reserved.
+ bool IsReservedName(const string& name) const;
+
// Source Location ---------------------------------------------------
// Updates |*out_location| to the source location of the complete
@@ -312,7 +352,7 @@ class LIBPROTOBUF_EXPORT Descriptor {
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
- void GetLocationPath(vector<int>* output) const;
+ void GetLocationPath(std::vector<int>* output) const;
const string* name_;
const string* full_name_;
@@ -337,6 +377,10 @@ class LIBPROTOBUF_EXPORT Descriptor {
ExtensionRange* extension_ranges_;
int extension_count_;
FieldDescriptor* extensions_;
+ int reserved_range_count_;
+ ReservedRange* reserved_ranges_;
+ int reserved_name_count_;
+ const string** reserved_names_;
// IMPORTANT: If you add a new field, make sure to search for all instances
// of Allocate<Descriptor>() and AllocateArray<Descriptor>() in descriptor.cc
// and update them to initialize the field.
@@ -594,7 +638,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
- void GetLocationPath(vector<int>* output) const;
+ void GetLocationPath(std::vector<int>* output) const;
const string* name_;
const string* full_name_;
@@ -688,7 +732,7 @@ class LIBPROTOBUF_EXPORT OneofDescriptor {
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
- void GetLocationPath(vector<int>* output) const;
+ void GetLocationPath(std::vector<int>* output) const;
const string* name_;
const string* full_name_;
@@ -790,7 +834,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptor {
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
- void GetLocationPath(vector<int>* output) const;
+ void GetLocationPath(std::vector<int>* output) const;
const string* name_;
const string* full_name_;
@@ -874,7 +918,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptor {
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
- void GetLocationPath(vector<int>* output) const;
+ void GetLocationPath(std::vector<int>* output) const;
const string* name_;
const string* full_name_;
@@ -949,7 +993,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptor {
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
- void GetLocationPath(vector<int>* output) const;
+ void GetLocationPath(std::vector<int>* output) const;
const string* name_;
const string* full_name_;
@@ -1028,7 +1072,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptor {
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
- void GetLocationPath(vector<int>* output) const;
+ void GetLocationPath(std::vector<int>* output) const;
const string* name_;
const string* full_name_;
@@ -1173,17 +1217,15 @@ class LIBPROTOBUF_EXPORT FileDescriptor {
// this file declaration (namely, the empty path).
bool GetSourceLocation(SourceLocation* out_location) const;
- private:
- // Source Location ---------------------------------------------------
-
// Updates |*out_location| to the source location of the complete
// extent of the declaration or declaration-part denoted by |path|.
// Returns false and leaves |*out_location| unchanged iff location
// information was not available. (See SourceCodeInfo for
// description of path encoding.)
- bool GetSourceLocation(const vector<int>& path,
+ bool GetSourceLocation(const std::vector<int>& path,
SourceLocation* out_location) const;
+ private:
typedef FileOptions OptionsType;
const string* name_;
@@ -1326,7 +1368,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
// found: extensions defined in the fallback database might not be found
// depending on the database implementation.
void FindAllExtensions(const Descriptor* extendee,
- vector<const FieldDescriptor*>* out) const;
+ std::vector<const FieldDescriptor*>* out) const;
// Building descriptors --------------------------------------------
@@ -1563,6 +1605,12 @@ PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension_range,
const Descriptor::ExtensionRange*)
PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension,
const FieldDescriptor*)
+
+PROTOBUF_DEFINE_ACCESSOR(Descriptor, reserved_range_count, int)
+PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, reserved_range,
+ const Descriptor::ReservedRange*)
+PROTOBUF_DEFINE_ACCESSOR(Descriptor, reserved_name_count, int)
+
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(Descriptor, MessageOptions);
PROTOBUF_DEFINE_ACCESSOR(Descriptor, is_placeholder, bool)
@@ -1663,6 +1711,25 @@ inline bool Descriptor::IsExtensionNumber(int number) const {
return FindExtensionRangeContainingNumber(number) != NULL;
}
+inline bool Descriptor::IsReservedNumber(int number) const {
+ return FindReservedRangeContainingNumber(number) != NULL;
+}
+
+inline bool Descriptor::IsReservedName(const string& name) const {
+ for (int i = 0; i < reserved_name_count(); i++) {
+ if (name == reserved_name(i)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Can't use PROTOBUF_DEFINE_ARRAY_ACCESSOR because reserved_names_ is actually
+// an array of pointers rather than the usual array of objects.
+inline const string& Descriptor::reserved_name(int index) const {
+ return *reserved_names_[index];
+}
+
inline bool FieldDescriptor::is_required() const {
return label() == LABEL_REQUIRED;
}
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 97121fa9..5e7eeaa7 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -33,6 +33,9 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
const ::google::protobuf::Descriptor* DescriptorProto_ExtensionRange_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
DescriptorProto_ExtensionRange_reflection_ = NULL;
+const ::google::protobuf::Descriptor* DescriptorProto_ReservedRange_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ DescriptorProto_ReservedRange_reflection_ = NULL;
const ::google::protobuf::Descriptor* FieldDescriptorProto_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
FieldDescriptorProto_reflection_ = NULL;
@@ -64,6 +67,7 @@ const ::google::protobuf::Descriptor* FieldOptions_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
FieldOptions_reflection_ = NULL;
const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor_ = NULL;
+const ::google::protobuf::EnumDescriptor* FieldOptions_JSType_descriptor_ = NULL;
const ::google::protobuf::Descriptor* EnumOptions_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
EnumOptions_reflection_ = NULL;
@@ -140,7 +144,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _internal_metadata_),
-1);
DescriptorProto_descriptor_ = file->message_type(2);
- static const int DescriptorProto_offsets_[8] = {
+ static const int DescriptorProto_offsets_[10] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, field_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, extension_),
@@ -149,6 +153,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, extension_range_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, oneof_decl_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, options_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, reserved_range_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, reserved_name_),
};
DescriptorProto_reflection_ =
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
@@ -177,6 +183,22 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
sizeof(DescriptorProto_ExtensionRange),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _internal_metadata_),
-1);
+ DescriptorProto_ReservedRange_descriptor_ = DescriptorProto_descriptor_->nested_type(1);
+ static const int DescriptorProto_ReservedRange_offsets_[2] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, start_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, end_),
+ };
+ DescriptorProto_ReservedRange_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ DescriptorProto_ReservedRange_descriptor_,
+ DescriptorProto_ReservedRange::default_instance_,
+ DescriptorProto_ReservedRange_offsets_,
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, _has_bits_[0]),
+ -1,
+ -1,
+ sizeof(DescriptorProto_ReservedRange),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, _internal_metadata_),
+ -1);
FieldDescriptorProto_descriptor_ = file->message_type(3);
static const int FieldDescriptorProto_offsets_[9] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, name_),
@@ -289,7 +311,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_[13] = {
+ static const int FileOptions_offsets_[16] = {
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_),
@@ -302,6 +324,9 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, py_generic_services_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, deprecated_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_enable_arenas_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, objc_class_prefix_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_namespace_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, javanano_use_deprecated_package_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_),
};
FileOptions_reflection_ =
@@ -336,9 +361,10 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _internal_metadata_),
-1);
FieldOptions_descriptor_ = file->message_type(11);
- static const int FieldOptions_offsets_[6] = {
+ static const int FieldOptions_offsets_[7] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, ctype_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, packed_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, jstype_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, lazy_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, deprecated_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, weak_),
@@ -356,6 +382,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _internal_metadata_),
-1);
FieldOptions_CType_descriptor_ = FieldOptions_descriptor_->enum_type(0);
+ FieldOptions_JSType_descriptor_ = FieldOptions_descriptor_->enum_type(1);
EnumOptions_descriptor_ = file->message_type(12);
static const int EnumOptions_offsets_[3] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, allow_alias_),
@@ -474,11 +501,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _internal_metadata_),
-1);
SourceCodeInfo_Location_descriptor_ = SourceCodeInfo_descriptor_->nested_type(0);
- static const int SourceCodeInfo_Location_offsets_[4] = {
+ static const int SourceCodeInfo_Location_offsets_[5] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, path_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, span_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_comments_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, trailing_comments_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_detached_comments_),
};
SourceCodeInfo_Location_reflection_ =
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
@@ -512,6 +540,8 @@ void protobuf_RegisterTypes(const ::std::string&) {
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
DescriptorProto_ExtensionRange_descriptor_, &DescriptorProto_ExtensionRange::default_instance());
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ DescriptorProto_ReservedRange_descriptor_, &DescriptorProto_ReservedRange::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
FieldDescriptorProto_descriptor_, &FieldDescriptorProto::default_instance());
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
OneofDescriptorProto_descriptor_, &OneofDescriptorProto::default_instance());
@@ -558,6 +588,8 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto() {
delete DescriptorProto_reflection_;
delete DescriptorProto_ExtensionRange::default_instance_;
delete DescriptorProto_ExtensionRange_reflection_;
+ delete DescriptorProto_ReservedRange::default_instance_;
+ delete DescriptorProto_ReservedRange_reflection_;
delete FieldDescriptorProto::default_instance_;
delete FieldDescriptorProto_reflection_;
delete OneofDescriptorProto::default_instance_;
@@ -616,7 +648,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"\022-\n\007options\030\010 \001(\0132\034.google.protobuf.File"
"Options\0229\n\020source_code_info\030\t \001(\0132\037.goog"
"le.protobuf.SourceCodeInfo\022\016\n\006syntax\030\014 \001"
- "(\t\"\344\003\n\017DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005"
+ "(\t\"\360\004\n\017DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005"
"field\030\002 \003(\0132%.google.protobuf.FieldDescr"
"iptorProto\0228\n\textension\030\006 \003(\0132%.google.p"
"rotobuf.FieldDescriptorProto\0225\n\013nested_t"
@@ -627,100 +659,112 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"ExtensionRange\0229\n\noneof_decl\030\010 \003(\0132%.goo"
"gle.protobuf.OneofDescriptorProto\0220\n\007opt"
"ions\030\007 \001(\0132\037.google.protobuf.MessageOpti"
- "ons\032,\n\016ExtensionRange\022\r\n\005start\030\001 \001(\005\022\013\n\003"
- "end\030\002 \001(\005\"\251\005\n\024FieldDescriptorProto\022\014\n\004na"
- "me\030\001 \001(\t\022\016\n\006number\030\003 \001(\005\022:\n\005label\030\004 \001(\0162"
- "+.google.protobuf.FieldDescriptorProto.L"
- "abel\0228\n\004type\030\005 \001(\0162*.google.protobuf.Fie"
- "ldDescriptorProto.Type\022\021\n\ttype_name\030\006 \001("
- "\t\022\020\n\010extendee\030\002 \001(\t\022\025\n\rdefault_value\030\007 \001"
- "(\t\022\023\n\013oneof_index\030\t \001(\005\022.\n\007options\030\010 \001(\013"
- "2\035.google.protobuf.FieldOptions\"\266\002\n\004Type"
- "\022\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYP"
- "E_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32"
- "\020\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r"
- "\n\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_G"
- "ROUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014"
- "\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE"
- "_SFIXED32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_S"
- "INT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005Label\022\022\n\016LAB"
- "EL_OPTIONAL\020\001\022\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LAB"
- "EL_REPEATED\020\003\"$\n\024OneofDescriptorProto\022\014\n"
- "\004name\030\001 \001(\t\"\214\001\n\023EnumDescriptorProto\022\014\n\004n"
- "ame\030\001 \001(\t\0228\n\005value\030\002 \003(\0132).google.protob"
- "uf.EnumValueDescriptorProto\022-\n\007options\030\003"
- " \001(\0132\034.google.protobuf.EnumOptions\"l\n\030En"
- "umValueDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006"
- "number\030\002 \001(\005\0222\n\007options\030\003 \001(\0132!.google.p"
- "rotobuf.EnumValueOptions\"\220\001\n\026ServiceDesc"
- "riptorProto\022\014\n\004name\030\001 \001(\t\0226\n\006method\030\002 \003("
- "\0132&.google.protobuf.MethodDescriptorProt"
- "o\0220\n\007options\030\003 \001(\0132\037.google.protobuf.Ser"
- "viceOptions\"\301\001\n\025MethodDescriptorProto\022\014\n"
- "\004name\030\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023\n\013outpu"
- "t_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.p"
- "rotobuf.MethodOptions\022\037\n\020client_streamin"
- "g\030\005 \001(\010:\005false\022\037\n\020server_streaming\030\006 \001(\010"
- ":\005false\"\314\004\n\013FileOptions\022\024\n\014java_package\030"
- "\001 \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023j"
- "ava_multiple_files\030\n \001(\010:\005false\022,\n\035java_"
- "generate_equals_and_hash\030\024 \001(\010:\005false\022%\n"
- "\026java_string_check_utf8\030\033 \001(\010:\005false\022F\n\014"
- "optimize_for\030\t \001(\0162).google.protobuf.Fil"
- "eOptions.OptimizeMode:\005SPEED\022\022\n\ngo_packa"
- "ge\030\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001(\010:\005f"
- "alse\022$\n\025java_generic_services\030\021 \001(\010:\005fal"
- "se\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031"
- "\n\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enable_a"
- "renas\030\037 \001(\010:\005false\022C\n\024uninterpreted_opti"
- "on\030\347\007 \003(\0132$.google.protobuf.Uninterprete"
- "dOption\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCO"
- "DE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346"
- "\001\n\016MessageOptions\022&\n\027message_set_wire_fo"
- "rmat\030\001 \001(\010:\005false\022.\n\037no_standard_descrip"
- "tor_accessor\030\002 \001(\010:\005false\022\031\n\ndeprecated\030"
- "\003 \001(\010:\005false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024unint"
- "erpreted_option\030\347\007 \003(\0132$.google.protobuf"
- ".UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\240\002\n\014Fiel"
- "dOptions\022:\n\005ctype\030\001 \001(\0162#.google.protobu"
- "f.FieldOptions.CType:\006STRING\022\016\n\006packed\030\002"
- " \001(\010\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecated\030"
- "\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024uni"
- "nterpreted_option\030\347\007 \003(\0132$.google.protob"
- "uf.UninterpretedOption\"/\n\005CType\022\n\n\006STRIN"
- "G\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200\200\200"
- "\200\002\"\215\001\n\013EnumOptions\022\023\n\013allow_alias\030\002 \001(\010\022"
- "\031\n\ndeprecated\030\003 \001(\010:\005false\022C\n\024uninterpre"
- "ted_option\030\347\007 \003(\0132$.google.protobuf.Unin"
- "terpretedOption*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueO"
- "ptions\022\031\n\ndeprecated\030\001 \001(\010:\005false\022C\n\024uni"
- "nterpreted_option\030\347\007 \003(\0132$.google.protob"
- "uf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016Ser"
- "viceOptions\022\031\n\ndeprecated\030! \001(\010:\005false\022C"
- "\n\024uninterpreted_option\030\347\007 \003(\0132$.google.p"
- "rotobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"z"
- "\n\rMethodOptions\022\031\n\ndeprecated\030! \001(\010:\005fal"
- "se\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goog"
- "le.protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200"
- "\200\002\"\236\002\n\023UninterpretedOption\022;\n\004name\030\002 \003(\013"
- "2-.google.protobuf.UninterpretedOption.N"
- "amePart\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022pos"
- "itive_int_value\030\004 \001(\004\022\032\n\022negative_int_va"
- "lue\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014strin"
- "g_value\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323"
- "\n\010NamePart\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_exte"
- "nsion\030\002 \002(\010\"\261\001\n\016SourceCodeInfo\022:\n\010locati"
- "on\030\001 \003(\0132(.google.protobuf.SourceCodeInf"
- "o.Location\032c\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001"
- "\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003"
- " \001(\t\022\031\n\021trailing_comments\030\004 \001(\tB)\n\023com.g"
- "oogle.protobufB\020DescriptorProtosH\001", 4554);
+ "ons\022F\n\016reserved_range\030\t \003(\0132..google.pro"
+ "tobuf.DescriptorProto.ReservedRange\022\025\n\rr"
+ "eserved_name\030\n \003(\t\032,\n\016ExtensionRange\022\r\n\005"
+ "start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\032+\n\rReservedRang"
+ "e\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\251\005\n\024FieldD"
+ "escriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\003"
+ " \001(\005\022:\n\005label\030\004 \001(\0162+.google.protobuf.Fi"
+ "eldDescriptorProto.Label\0228\n\004type\030\005 \001(\0162*"
+ ".google.protobuf.FieldDescriptorProto.Ty"
+ "pe\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010extendee\030\002 \001(\t\022"
+ "\025\n\rdefault_value\030\007 \001(\t\022\023\n\013oneof_index\030\t "
+ "\001(\005\022.\n\007options\030\010 \001(\0132\035.google.protobuf.F"
+ "ieldOptions\"\266\002\n\004Type\022\017\n\013TYPE_DOUBLE\020\001\022\016\n"
+ "\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYPE_UI"
+ "NT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED64\020\006"
+ "\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022\017\n\013TYP"
+ "E_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_MESSA"
+ "GE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020\r\022\r\n"
+ "\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rTYPE_"
+ "SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_SINT"
+ "64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n\016LAB"
+ "EL_REQUIRED\020\002\022\022\n\016LABEL_REPEATED\020\003\"$\n\024One"
+ "ofDescriptorProto\022\014\n\004name\030\001 \001(\t\"\214\001\n\023Enum"
+ "DescriptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005value\030\002"
+ " \003(\0132).google.protobuf.EnumValueDescript"
+ "orProto\022-\n\007options\030\003 \001(\0132\034.google.protob"
+ "uf.EnumOptions\"l\n\030EnumValueDescriptorPro"
+ "to\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007opti"
+ "ons\030\003 \001(\0132!.google.protobuf.EnumValueOpt"
+ "ions\"\220\001\n\026ServiceDescriptorProto\022\014\n\004name\030"
+ "\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.protobuf."
+ "MethodDescriptorProto\0220\n\007options\030\003 \001(\0132\037"
+ ".google.protobuf.ServiceOptions\"\301\001\n\025Meth"
+ "odDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\ninput"
+ "_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n\007opti"
+ "ons\030\004 \001(\0132\036.google.protobuf.MethodOption"
+ "s\022\037\n\020client_streaming\030\005 \001(\010:\005false\022\037\n\020se"
+ "rver_streaming\030\006 \001(\010:\005false\"\252\005\n\013FileOpti"
+ "ons\022\024\n\014java_package\030\001 \001(\t\022\034\n\024java_outer_"
+ "classname\030\010 \001(\t\022\"\n\023java_multiple_files\030\n"
+ " \001(\010:\005false\022,\n\035java_generate_equals_and_"
+ "hash\030\024 \001(\010:\005false\022%\n\026java_string_check_u"
+ "tf8\030\033 \001(\010:\005false\022F\n\014optimize_for\030\t \001(\0162)"
+ ".google.protobuf.FileOptions.OptimizeMod"
+ "e:\005SPEED\022\022\n\ngo_package\030\013 \001(\t\022\"\n\023cc_gener"
+ "ic_services\030\020 \001(\010:\005false\022$\n\025java_generic"
+ "_services\030\021 \001(\010:\005false\022\"\n\023py_generic_ser"
+ "vices\030\022 \001(\010:\005false\022\031\n\ndeprecated\030\027 \001(\010:\005"
+ "false\022\037\n\020cc_enable_arenas\030\037 \001(\010:\005false\022\031"
+ "\n\021objc_class_prefix\030$ \001(\t\022\030\n\020csharp_name"
+ "space\030% \001(\t\022\'\n\037javanano_use_deprecated_p"
+ "ackage\030& \001(\010\022C\n\024uninterpreted_option\030\347\007 "
+ "\003(\0132$.google.protobuf.UninterpretedOptio"
+ "n\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZ"
+ "E\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016Mes"
+ "sageOptions\022&\n\027message_set_wire_format\030\001"
+ " \001(\010:\005false\022.\n\037no_standard_descriptor_ac"
+ "cessor\030\002 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:"
+ "\005false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024uninterpret"
+ "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint"
+ "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"\230\003\n\014FieldOptio"
+ "ns\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Fiel"
+ "dOptions.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\?"
+ "\n\006jstype\030\006 \001(\0162$.google.protobuf.FieldOp"
+ "tions.JSType:\tJS_NORMAL\022\023\n\004lazy\030\005 \001(\010:\005f"
+ "alse\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\023\n\004weak\030"
+ "\n \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 "
+ "\003(\0132$.google.protobuf.UninterpretedOptio"
+ "n\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRI"
+ "NG_PIECE\020\002\"5\n\006JSType\022\r\n\tJS_NORMAL\020\000\022\r\n\tJ"
+ "S_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\013allow_alias\030\002 \001(\010\022\031\n\ndep"
+ "recated\030\003 \001(\010:\005false\022C\n\024uninterpreted_op"
+ "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre"
+ "tedOption*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueOptions"
+ "\022\031\n\ndeprecated\030\001 \001(\010:\005false\022C\n\024uninterpr"
+ "eted_option\030\347\007 \003(\0132$.google.protobuf.Uni"
+ "nterpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOp"
+ "tions\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024unin"
+ "terpreted_option\030\347\007 \003(\0132$.google.protobu"
+ "f.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMeth"
+ "odOptions\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024"
+ "uninterpreted_option\030\347\007 \003(\0132$.google.pro"
+ "tobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n"
+ "\023UninterpretedOption\022;\n\004name\030\002 \003(\0132-.goo"
+ "gle.protobuf.UninterpretedOption.NamePar"
+ "t\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_value\030\006 \001(\001\022\024\n\014string_valu"
+ "e\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010Name"
+ "Part\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extension\030"
+ "\002 \002(\010\"\325\001\n\016SourceCodeInfo\022:\n\010location\030\001 \003"
+ "(\0132(.google.protobuf.SourceCodeInfo.Loca"
+ "tion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004s"
+ "pan\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022"
+ "\031\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_de"
+ "tached_comments\030\006 \003(\tB[\n\023com.google.prot"
+ "obufB\020DescriptorProtosH\001Z\ndescriptor\242\002\003G"
+ "PB\252\002\032Google.Protobuf.Reflection\260\002\001", 4994);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
FileDescriptorSet::default_instance_ = new FileDescriptorSet();
FileDescriptorProto::default_instance_ = new FileDescriptorProto();
DescriptorProto::default_instance_ = new DescriptorProto();
DescriptorProto_ExtensionRange::default_instance_ = new DescriptorProto_ExtensionRange();
+ DescriptorProto_ReservedRange::default_instance_ = new DescriptorProto_ReservedRange();
FieldDescriptorProto::default_instance_ = new FieldDescriptorProto();
OneofDescriptorProto::default_instance_ = new OneofDescriptorProto();
EnumDescriptorProto::default_instance_ = new EnumDescriptorProto();
@@ -742,6 +786,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
FileDescriptorProto::default_instance_->InitAsDefaultInstance();
DescriptorProto::default_instance_->InitAsDefaultInstance();
DescriptorProto_ExtensionRange::default_instance_->InitAsDefaultInstance();
+ DescriptorProto_ReservedRange::default_instance_->InitAsDefaultInstance();
FieldDescriptorProto::default_instance_->InitAsDefaultInstance();
OneofDescriptorProto::default_instance_->InitAsDefaultInstance();
EnumDescriptorProto::default_instance_->InitAsDefaultInstance();
@@ -786,7 +831,7 @@ const int FileDescriptorSet::kFileFieldNumber;
#endif // !_MSC_VER
FileDescriptorSet::FileDescriptorSet()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorSet)
}
@@ -863,13 +908,15 @@ bool FileDescriptorSet::MergePartialFromCodedStream(
// repeated .google.protobuf.FileDescriptorProto file = 1;
case 1: {
if (tag == 10) {
- parse_file:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_file:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_file()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(10)) goto parse_file;
+ if (input->ExpectTag(10)) goto parse_loop_file;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -954,9 +1001,9 @@ int FileDescriptorSet::ByteSize() const {
void FileDescriptorSet::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const FileDescriptorSet* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const FileDescriptorSet*>(
- &from);
+ const FileDescriptorSet* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorSet>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -1009,6 +1056,40 @@ void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FileDescriptorSet
+
+// repeated .google.protobuf.FileDescriptorProto file = 1;
+int FileDescriptorSet::file_size() const {
+ return file_.size();
+}
+void FileDescriptorSet::clear_file() {
+ file_.Clear();
+}
+ const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorSet.file)
+ return file_.Get(index);
+}
+ ::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorSet.file)
+ return file_.Mutable(index);
+}
+ ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() {
+ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file)
+ return file_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+FileDescriptorSet::file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file)
+ return file_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+FileDescriptorSet::mutable_file() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file)
+ return &file_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -1028,7 +1109,7 @@ const int FileDescriptorProto::kSyntaxFieldNumber;
#endif // !_MSC_VER
FileDescriptorProto::FileDescriptorProto()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorProto)
}
@@ -1098,7 +1179,7 @@ FileDescriptorProto* FileDescriptorProto::New(::google::protobuf::Arena* arena)
}
void FileDescriptorProto::Clear() {
- if (_has_bits_[0 / 32] & 3) {
+ if (_has_bits_[0 / 32] & 3u) {
if (has_name()) {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1106,7 +1187,7 @@ void FileDescriptorProto::Clear() {
package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
}
- if (_has_bits_[8 / 32] & 3584) {
+ if (_has_bits_[8 / 32] & 3584u) {
if (has_options()) {
if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
}
@@ -1196,54 +1277,63 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
case 4: {
if (tag == 34) {
parse_message_type:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_message_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_message_type()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(34)) goto parse_message_type;
- if (input->ExpectTag(42)) goto parse_enum_type;
+ if (input->ExpectTag(34)) goto parse_loop_message_type;
+ if (input->ExpectTag(42)) goto parse_loop_enum_type;
+ input->UnsafeDecrementRecursionDepth();
break;
}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
case 5: {
if (tag == 42) {
- parse_enum_type:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_enum_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_enum_type()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(42)) goto parse_enum_type;
- if (input->ExpectTag(50)) goto parse_service;
+ if (input->ExpectTag(42)) goto parse_loop_enum_type;
+ if (input->ExpectTag(50)) goto parse_loop_service;
+ input->UnsafeDecrementRecursionDepth();
break;
}
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
case 6: {
if (tag == 50) {
- parse_service:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_service:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_service()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(50)) goto parse_service;
- if (input->ExpectTag(58)) goto parse_extension;
+ if (input->ExpectTag(50)) goto parse_loop_service;
+ if (input->ExpectTag(58)) goto parse_loop_extension;
+ input->UnsafeDecrementRecursionDepth();
break;
}
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
case 7: {
if (tag == 58) {
- parse_extension:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_extension:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_extension()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(58)) goto parse_extension;
+ if (input->ExpectTag(58)) goto parse_loop_extension;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectTag(66)) goto parse_options;
break;
}
@@ -1560,7 +1650,7 @@ void FileDescriptorProto::SerializeWithCachedSizes(
int FileDescriptorProto::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & 3) {
+ if (_has_bits_[0 / 32] & 3u) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -1576,7 +1666,7 @@ int FileDescriptorProto::ByteSize() const {
}
}
- if (_has_bits_[9 / 32] & 3584) {
+ if (_has_bits_[9 / 32] & 3584u) {
// optional .google.protobuf.FileOptions options = 8;
if (has_options()) {
total_size += 1 +
@@ -1671,9 +1761,9 @@ int FileDescriptorProto::ByteSize() const {
void FileDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const FileDescriptorProto* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const FileDescriptorProto*>(
- &from);
+ const FileDescriptorProto* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorProto>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -1771,6 +1861,489 @@ void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FileDescriptorProto
+
+// optional string name = 1;
+bool FileDescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void FileDescriptorProto::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void FileDescriptorProto::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void FileDescriptorProto::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& FileDescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.name)
+}
+ void FileDescriptorProto::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.name)
+}
+ void FileDescriptorProto::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.name)
+}
+ ::std::string* FileDescriptorProto::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileDescriptorProto::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name)
+}
+
+// optional string package = 2;
+bool FileDescriptorProto::has_package() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void FileDescriptorProto::set_has_package() {
+ _has_bits_[0] |= 0x00000002u;
+}
+void FileDescriptorProto::clear_has_package() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+void FileDescriptorProto::clear_package() {
+ package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_package();
+}
+ const ::std::string& FileDescriptorProto::package() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.package)
+ return package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_package(const ::std::string& value) {
+ set_has_package();
+ package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.package)
+}
+ void FileDescriptorProto::set_package(const char* value) {
+ set_has_package();
+ package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.package)
+}
+ void FileDescriptorProto::set_package(const char* value, size_t size) {
+ set_has_package();
+ package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.package)
+}
+ ::std::string* FileDescriptorProto::mutable_package() {
+ set_has_package();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.package)
+ return package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileDescriptorProto::release_package() {
+ clear_has_package();
+ return package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_allocated_package(::std::string* package) {
+ if (package != NULL) {
+ set_has_package();
+ } else {
+ clear_has_package();
+ }
+ package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), package);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package)
+}
+
+// repeated string dependency = 3;
+int FileDescriptorProto::dependency_size() const {
+ return dependency_.size();
+}
+void FileDescriptorProto::clear_dependency() {
+ dependency_.Clear();
+}
+ const ::std::string& FileDescriptorProto::dependency(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.dependency)
+ return dependency_.Get(index);
+}
+ ::std::string* FileDescriptorProto::mutable_dependency(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.dependency)
+ return dependency_.Mutable(index);
+}
+ void FileDescriptorProto::set_dependency(int index, const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency)
+ dependency_.Mutable(index)->assign(value);
+}
+ void FileDescriptorProto::set_dependency(int index, const char* value) {
+ dependency_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.dependency)
+}
+ void FileDescriptorProto::set_dependency(int index, const char* value, size_t size) {
+ dependency_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency)
+}
+ ::std::string* FileDescriptorProto::add_dependency() {
+ return dependency_.Add();
+}
+ void FileDescriptorProto::add_dependency(const ::std::string& value) {
+ dependency_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency)
+}
+ void FileDescriptorProto::add_dependency(const char* value) {
+ dependency_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.FileDescriptorProto.dependency)
+}
+ void FileDescriptorProto::add_dependency(const char* value, size_t size) {
+ dependency_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.FileDescriptorProto.dependency)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+FileDescriptorProto::dependency() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.dependency)
+ return dependency_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+FileDescriptorProto::mutable_dependency() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.dependency)
+ return &dependency_;
+}
+
+// repeated int32 public_dependency = 10;
+int FileDescriptorProto::public_dependency_size() const {
+ return public_dependency_.size();
+}
+void FileDescriptorProto::clear_public_dependency() {
+ public_dependency_.Clear();
+}
+ ::google::protobuf::int32 FileDescriptorProto::public_dependency(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.public_dependency)
+ return public_dependency_.Get(index);
+}
+ void FileDescriptorProto::set_public_dependency(int index, ::google::protobuf::int32 value) {
+ public_dependency_.Set(index, value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.public_dependency)
+}
+ void FileDescriptorProto::add_public_dependency(::google::protobuf::int32 value) {
+ public_dependency_.Add(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.public_dependency)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+FileDescriptorProto::public_dependency() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.public_dependency)
+ return public_dependency_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+FileDescriptorProto::mutable_public_dependency() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.public_dependency)
+ return &public_dependency_;
+}
+
+// repeated int32 weak_dependency = 11;
+int FileDescriptorProto::weak_dependency_size() const {
+ return weak_dependency_.size();
+}
+void FileDescriptorProto::clear_weak_dependency() {
+ weak_dependency_.Clear();
+}
+ ::google::protobuf::int32 FileDescriptorProto::weak_dependency(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.weak_dependency)
+ return weak_dependency_.Get(index);
+}
+ void FileDescriptorProto::set_weak_dependency(int index, ::google::protobuf::int32 value) {
+ weak_dependency_.Set(index, value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.weak_dependency)
+}
+ void FileDescriptorProto::add_weak_dependency(::google::protobuf::int32 value) {
+ weak_dependency_.Add(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.weak_dependency)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+FileDescriptorProto::weak_dependency() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.weak_dependency)
+ return weak_dependency_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+FileDescriptorProto::mutable_weak_dependency() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.weak_dependency)
+ return &weak_dependency_;
+}
+
+// repeated .google.protobuf.DescriptorProto message_type = 4;
+int FileDescriptorProto::message_type_size() const {
+ return message_type_.size();
+}
+void FileDescriptorProto::clear_message_type() {
+ message_type_.Clear();
+}
+ const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.message_type)
+ return message_type_.Get(index);
+}
+ ::google::protobuf::DescriptorProto* FileDescriptorProto::mutable_message_type(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.message_type)
+ return message_type_.Mutable(index);
+}
+ ::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_type() {
+ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type)
+ return message_type_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+FileDescriptorProto::message_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type)
+ return message_type_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+FileDescriptorProto::mutable_message_type() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type)
+ return &message_type_;
+}
+
+// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
+int FileDescriptorProto::enum_type_size() const {
+ return enum_type_.size();
+}
+void FileDescriptorProto::clear_enum_type() {
+ enum_type_.Clear();
+}
+ const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.enum_type)
+ return enum_type_.Get(index);
+}
+ ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::mutable_enum_type(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.enum_type)
+ return enum_type_.Mutable(index);
+}
+ ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_type() {
+ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type)
+ return enum_type_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+FileDescriptorProto::enum_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type)
+ return enum_type_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+FileDescriptorProto::mutable_enum_type() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type)
+ return &enum_type_;
+}
+
+// repeated .google.protobuf.ServiceDescriptorProto service = 6;
+int FileDescriptorProto::service_size() const {
+ return service_.size();
+}
+void FileDescriptorProto::clear_service() {
+ service_.Clear();
+}
+ const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.service)
+ return service_.Get(index);
+}
+ ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::mutable_service(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.service)
+ return service_.Mutable(index);
+}
+ ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_service() {
+ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service)
+ return service_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+FileDescriptorProto::service() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service)
+ return service_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
+FileDescriptorProto::mutable_service() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service)
+ return &service_;
+}
+
+// repeated .google.protobuf.FieldDescriptorProto extension = 7;
+int FileDescriptorProto::extension_size() const {
+ return extension_.size();
+}
+void FileDescriptorProto::clear_extension() {
+ extension_.Clear();
+}
+ const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.extension)
+ return extension_.Get(index);
+}
+ ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::mutable_extension(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.extension)
+ return extension_.Mutable(index);
+}
+ ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extension() {
+ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension)
+ return extension_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+FileDescriptorProto::extension() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension)
+ return extension_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+FileDescriptorProto::mutable_extension() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension)
+ return &extension_;
+}
+
+// optional .google.protobuf.FileOptions options = 8;
+bool FileDescriptorProto::has_options() const {
+ return (_has_bits_[0] & 0x00000200u) != 0;
+}
+void FileDescriptorProto::set_has_options() {
+ _has_bits_[0] |= 0x00000200u;
+}
+void FileDescriptorProto::clear_has_options() {
+ _has_bits_[0] &= ~0x00000200u;
+}
+void FileDescriptorProto::clear_options() {
+ if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
+ clear_has_options();
+}
+ const ::google::protobuf::FileOptions& FileDescriptorProto::options() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options)
+ return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() {
+ set_has_options();
+ if (options_ == NULL) {
+ options_ = new ::google::protobuf::FileOptions;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options)
+ return options_;
+}
+ ::google::protobuf::FileOptions* FileDescriptorProto::release_options() {
+ clear_has_options();
+ ::google::protobuf::FileOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+}
+ void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.options)
+}
+
+// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+bool FileDescriptorProto::has_source_code_info() const {
+ return (_has_bits_[0] & 0x00000400u) != 0;
+}
+void FileDescriptorProto::set_has_source_code_info() {
+ _has_bits_[0] |= 0x00000400u;
+}
+void FileDescriptorProto::clear_has_source_code_info() {
+ _has_bits_[0] &= ~0x00000400u;
+}
+void FileDescriptorProto::clear_source_code_info() {
+ if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
+ clear_has_source_code_info();
+}
+ const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info)
+ return source_code_info_ != NULL ? *source_code_info_ : *default_instance_->source_code_info_;
+}
+ ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() {
+ set_has_source_code_info();
+ if (source_code_info_ == NULL) {
+ source_code_info_ = new ::google::protobuf::SourceCodeInfo;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info)
+ return source_code_info_;
+}
+ ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() {
+ clear_has_source_code_info();
+ ::google::protobuf::SourceCodeInfo* temp = source_code_info_;
+ source_code_info_ = NULL;
+ return temp;
+}
+ void FileDescriptorProto::set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info) {
+ delete source_code_info_;
+ source_code_info_ = source_code_info;
+ if (source_code_info) {
+ set_has_source_code_info();
+ } else {
+ clear_has_source_code_info();
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.source_code_info)
+}
+
+// optional string syntax = 12;
+bool FileDescriptorProto::has_syntax() const {
+ return (_has_bits_[0] & 0x00000800u) != 0;
+}
+void FileDescriptorProto::set_has_syntax() {
+ _has_bits_[0] |= 0x00000800u;
+}
+void FileDescriptorProto::clear_has_syntax() {
+ _has_bits_[0] &= ~0x00000800u;
+}
+void FileDescriptorProto::clear_syntax() {
+ syntax_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_syntax();
+}
+ const ::std::string& FileDescriptorProto::syntax() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.syntax)
+ return syntax_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_syntax(const ::std::string& value) {
+ set_has_syntax();
+ syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.syntax)
+}
+ void FileDescriptorProto::set_syntax(const char* value) {
+ set_has_syntax();
+ syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.syntax)
+}
+ void FileDescriptorProto::set_syntax(const char* value, size_t size) {
+ set_has_syntax();
+ syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.syntax)
+}
+ ::std::string* FileDescriptorProto::mutable_syntax() {
+ set_has_syntax();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.syntax)
+ return syntax_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileDescriptorProto::release_syntax() {
+ clear_has_syntax();
+ return syntax_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_allocated_syntax(::std::string* syntax) {
+ if (syntax != NULL) {
+ set_has_syntax();
+ } else {
+ clear_has_syntax();
+ }
+ syntax_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), syntax);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -1780,7 +2353,7 @@ const int DescriptorProto_ExtensionRange::kEndFieldNumber;
#endif // !_MSC_VER
DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto.ExtensionRange)
}
@@ -1839,19 +2412,17 @@ DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::New(::google::pr
}
void DescriptorProto_ExtensionRange::Clear() {
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
- &reinterpret_cast<DescriptorProto_ExtensionRange*>(16)->f) - \
- reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<DescriptorProto_ExtensionRange*>(16)->f)
-#define ZR_(first, last) do { \
- size_t f = OFFSET_OF_FIELD_(first); \
- size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \
- ::memset(&first, 0, n); \
- } while (0)
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
ZR_(start_, end_);
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
#undef ZR_
::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -1965,7 +2536,7 @@ void DescriptorProto_ExtensionRange::SerializeWithCachedSizes(
int DescriptorProto_ExtensionRange::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & 3) {
+ if (_has_bits_[0 / 32] & 3u) {
// optional int32 start = 1;
if (has_start()) {
total_size += 1 +
@@ -1994,9 +2565,9 @@ int DescriptorProto_ExtensionRange::ByteSize() const {
void DescriptorProto_ExtensionRange::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const DescriptorProto_ExtensionRange* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const DescriptorProto_ExtensionRange*>(
- &from);
+ const DescriptorProto_ExtensionRange* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto_ExtensionRange>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -2060,6 +2631,289 @@ void DescriptorProto_ExtensionRange::InternalSwap(DescriptorProto_ExtensionRange
// -------------------------------------------------------------------
#ifndef _MSC_VER
+const int DescriptorProto_ReservedRange::kStartFieldNumber;
+const int DescriptorProto_ReservedRange::kEndFieldNumber;
+#endif // !_MSC_VER
+
+DescriptorProto_ReservedRange::DescriptorProto_ReservedRange()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto.ReservedRange)
+}
+
+void DescriptorProto_ReservedRange::InitAsDefaultInstance() {
+}
+
+DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ReservedRange)
+}
+
+void DescriptorProto_ReservedRange::SharedCtor() {
+ _cached_size_ = 0;
+ start_ = 0;
+ end_ = 0;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+DescriptorProto_ReservedRange::~DescriptorProto_ReservedRange() {
+ // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto.ReservedRange)
+ SharedDtor();
+}
+
+void DescriptorProto_ReservedRange::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void DescriptorProto_ReservedRange::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* DescriptorProto_ReservedRange::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return DescriptorProto_ReservedRange_descriptor_;
+}
+
+const DescriptorProto_ReservedRange& DescriptorProto_ReservedRange::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ return *default_instance_;
+}
+
+DescriptorProto_ReservedRange* DescriptorProto_ReservedRange::default_instance_ = NULL;
+
+DescriptorProto_ReservedRange* DescriptorProto_ReservedRange::New(::google::protobuf::Arena* arena) const {
+ DescriptorProto_ReservedRange* n = new DescriptorProto_ReservedRange;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void DescriptorProto_ReservedRange::Clear() {
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<DescriptorProto_ReservedRange*>(16)->f)
+
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+ ZR_(start_, end_);
+
+#undef ZR_HELPER_
+#undef ZR_
+
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
+}
+
+bool DescriptorProto_ReservedRange::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto.ReservedRange)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional int32 start = 1;
+ case 1: {
+ if (tag == 8) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &start_)));
+ set_has_start();
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(16)) goto parse_end;
+ break;
+ }
+
+ // optional int32 end = 2;
+ case 2: {
+ if (tag == 16) {
+ parse_end:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &end_)));
+ set_has_end();
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormat::SkipField(
+ input, tag, mutable_unknown_fields()));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.DescriptorProto.ReservedRange)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.DescriptorProto.ReservedRange)
+ return false;
+#undef DO_
+}
+
+void DescriptorProto_ReservedRange::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.DescriptorProto.ReservedRange)
+ // optional int32 start = 1;
+ if (has_start()) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output);
+ }
+
+ // optional int32 end = 2;
+ if (has_end()) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output);
+ }
+
+ if (_internal_metadata_.have_unknown_fields()) {
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
+ }
+ // @@protoc_insertion_point(serialize_end:google.protobuf.DescriptorProto.ReservedRange)
+}
+
+::google::protobuf::uint8* DescriptorProto_ReservedRange::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ReservedRange)
+ // optional int32 start = 1;
+ if (has_start()) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target);
+ }
+
+ // optional int32 end = 2;
+ if (has_end()) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target);
+ }
+
+ if (_internal_metadata_.have_unknown_fields()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ReservedRange)
+ return target;
+}
+
+int DescriptorProto_ReservedRange::ByteSize() const {
+ int total_size = 0;
+
+ if (_has_bits_[0 / 32] & 3u) {
+ // optional int32 start = 1;
+ if (has_start()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->start());
+ }
+
+ // optional int32 end = 2;
+ if (has_end()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->end());
+ }
+
+ }
+ if (_internal_metadata_.have_unknown_fields()) {
+ total_size +=
+ ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+ unknown_fields());
+ }
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void DescriptorProto_ReservedRange::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const DescriptorProto_ReservedRange* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto_ReservedRange>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void DescriptorProto_ReservedRange::MergeFrom(const DescriptorProto_ReservedRange& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (from.has_start()) {
+ set_start(from.start());
+ }
+ if (from.has_end()) {
+ set_end(from.end());
+ }
+ }
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
+}
+
+void DescriptorProto_ReservedRange::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void DescriptorProto_ReservedRange::CopyFrom(const DescriptorProto_ReservedRange& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool DescriptorProto_ReservedRange::IsInitialized() const {
+
+ return true;
+}
+
+void DescriptorProto_ReservedRange::Swap(DescriptorProto_ReservedRange* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void DescriptorProto_ReservedRange::InternalSwap(DescriptorProto_ReservedRange* other) {
+ std::swap(start_, other->start_);
+ std::swap(end_, other->end_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata DescriptorProto_ReservedRange::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = DescriptorProto_ReservedRange_descriptor_;
+ metadata.reflection = DescriptorProto_ReservedRange_reflection_;
+ return metadata;
+}
+
+
+// -------------------------------------------------------------------
+
+#ifndef _MSC_VER
const int DescriptorProto::kNameFieldNumber;
const int DescriptorProto::kFieldFieldNumber;
const int DescriptorProto::kExtensionFieldNumber;
@@ -2068,10 +2922,12 @@ const int DescriptorProto::kEnumTypeFieldNumber;
const int DescriptorProto::kExtensionRangeFieldNumber;
const int DescriptorProto::kOneofDeclFieldNumber;
const int DescriptorProto::kOptionsFieldNumber;
+const int DescriptorProto::kReservedRangeFieldNumber;
+const int DescriptorProto::kReservedNameFieldNumber;
#endif // !_MSC_VER
DescriptorProto::DescriptorProto()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto)
}
@@ -2134,7 +2990,7 @@ DescriptorProto* DescriptorProto::New(::google::protobuf::Arena* arena) const {
}
void DescriptorProto::Clear() {
- if (_has_bits_[0 / 32] & 129) {
+ if (_has_bits_[0 / 32] & 129u) {
if (has_name()) {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -2148,6 +3004,8 @@ void DescriptorProto::Clear() {
enum_type_.Clear();
extension_range_.Clear();
oneof_decl_.Clear();
+ reserved_range_.Clear();
+ reserved_name_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
if (_internal_metadata_.have_unknown_fields()) {
mutable_unknown_fields()->Clear();
@@ -2184,68 +3042,79 @@ bool DescriptorProto::MergePartialFromCodedStream(
case 2: {
if (tag == 18) {
parse_field:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_field:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_field()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(18)) goto parse_field;
- if (input->ExpectTag(26)) goto parse_nested_type;
+ if (input->ExpectTag(18)) goto parse_loop_field;
+ if (input->ExpectTag(26)) goto parse_loop_nested_type;
+ input->UnsafeDecrementRecursionDepth();
break;
}
// repeated .google.protobuf.DescriptorProto nested_type = 3;
case 3: {
if (tag == 26) {
- parse_nested_type:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_nested_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_nested_type()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(26)) goto parse_nested_type;
- if (input->ExpectTag(34)) goto parse_enum_type;
+ if (input->ExpectTag(26)) goto parse_loop_nested_type;
+ if (input->ExpectTag(34)) goto parse_loop_enum_type;
+ input->UnsafeDecrementRecursionDepth();
break;
}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
case 4: {
if (tag == 34) {
- parse_enum_type:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_enum_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_enum_type()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(34)) goto parse_enum_type;
- if (input->ExpectTag(42)) goto parse_extension_range;
+ if (input->ExpectTag(34)) goto parse_loop_enum_type;
+ if (input->ExpectTag(42)) goto parse_loop_extension_range;
+ input->UnsafeDecrementRecursionDepth();
break;
}
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
case 5: {
if (tag == 42) {
- parse_extension_range:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_extension_range:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_extension_range()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(42)) goto parse_extension_range;
- if (input->ExpectTag(50)) goto parse_extension;
+ if (input->ExpectTag(42)) goto parse_loop_extension_range;
+ if (input->ExpectTag(50)) goto parse_loop_extension;
+ input->UnsafeDecrementRecursionDepth();
break;
}
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
case 6: {
if (tag == 50) {
- parse_extension:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_extension:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_extension()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(50)) goto parse_extension;
+ if (input->ExpectTag(50)) goto parse_loop_extension;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectTag(58)) goto parse_options;
break;
}
@@ -2267,12 +3136,50 @@ bool DescriptorProto::MergePartialFromCodedStream(
case 8: {
if (tag == 66) {
parse_oneof_decl:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_oneof_decl:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_oneof_decl()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(66)) goto parse_oneof_decl;
+ if (input->ExpectTag(66)) goto parse_loop_oneof_decl;
+ if (input->ExpectTag(74)) goto parse_loop_reserved_range;
+ input->UnsafeDecrementRecursionDepth();
+ break;
+ }
+
+ // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+ case 9: {
+ if (tag == 74) {
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_reserved_range:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ input, add_reserved_range()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(74)) goto parse_loop_reserved_range;
+ input->UnsafeDecrementRecursionDepth();
+ if (input->ExpectTag(82)) goto parse_reserved_name;
+ break;
+ }
+
+ // repeated string reserved_name = 10;
+ case 10: {
+ if (tag == 82) {
+ parse_reserved_name:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->add_reserved_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->reserved_name(this->reserved_name_size() - 1).data(),
+ this->reserved_name(this->reserved_name_size() - 1).length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.DescriptorProto.reserved_name");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(82)) goto parse_reserved_name;
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -2354,6 +3261,22 @@ void DescriptorProto::SerializeWithCachedSizes(
8, this->oneof_decl(i), output);
}
+ // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+ for (unsigned int i = 0, n = this->reserved_range_size(); i < n; i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 9, this->reserved_range(i), output);
+ }
+
+ // repeated string reserved_name = 10;
+ for (int i = 0; i < this->reserved_name_size(); i++) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->reserved_name(i).data(), this->reserved_name(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.DescriptorProto.reserved_name");
+ ::google::protobuf::internal::WireFormatLite::WriteString(
+ 10, this->reserved_name(i), output);
+ }
+
if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
@@ -2424,6 +3347,23 @@ void DescriptorProto::SerializeWithCachedSizes(
8, this->oneof_decl(i), target);
}
+ // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+ for (unsigned int i = 0, n = this->reserved_range_size(); i < n; i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 9, this->reserved_range(i), target);
+ }
+
+ // repeated string reserved_name = 10;
+ for (int i = 0; i < this->reserved_name_size(); i++) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->reserved_name(i).data(), this->reserved_name(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.DescriptorProto.reserved_name");
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteStringToArray(10, this->reserved_name(i), target);
+ }
+
if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -2435,7 +3375,7 @@ void DescriptorProto::SerializeWithCachedSizes(
int DescriptorProto::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & 129) {
+ if (_has_bits_[0 / 32] & 129u) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -2499,6 +3439,21 @@ int DescriptorProto::ByteSize() const {
this->oneof_decl(i));
}
+ // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+ total_size += 1 * this->reserved_range_size();
+ for (int i = 0; i < this->reserved_range_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->reserved_range(i));
+ }
+
+ // repeated string reserved_name = 10;
+ total_size += 1 * this->reserved_name_size();
+ for (int i = 0; i < this->reserved_name_size(); i++) {
+ total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->reserved_name(i));
+ }
+
if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
@@ -2512,9 +3467,9 @@ int DescriptorProto::ByteSize() const {
void DescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const DescriptorProto* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const DescriptorProto*>(
- &from);
+ const DescriptorProto* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -2530,6 +3485,8 @@ void DescriptorProto::MergeFrom(const DescriptorProto& from) {
enum_type_.MergeFrom(from.enum_type_);
extension_range_.MergeFrom(from.extension_range_);
oneof_decl_.MergeFrom(from.oneof_decl_);
+ reserved_range_.MergeFrom(from.reserved_range_);
+ reserved_name_.MergeFrom(from.reserved_name_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name()) {
set_has_name();
@@ -2581,6 +3538,8 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) {
extension_range_.UnsafeArenaSwap(&other->extension_range_);
oneof_decl_.UnsafeArenaSwap(&other->oneof_decl_);
std::swap(options_, other->options_);
+ reserved_range_.UnsafeArenaSwap(&other->reserved_range_);
+ reserved_name_.UnsafeArenaSwap(&other->reserved_name_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_internal_metadata_.Swap(&other->_internal_metadata_);
std::swap(_cached_size_, other->_cached_size_);
@@ -2594,6 +3553,474 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// DescriptorProto_ExtensionRange
+
+// optional int32 start = 1;
+bool DescriptorProto_ExtensionRange::has_start() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void DescriptorProto_ExtensionRange::set_has_start() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void DescriptorProto_ExtensionRange::clear_has_start() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void DescriptorProto_ExtensionRange::clear_start() {
+ start_ = 0;
+ clear_has_start();
+}
+ ::google::protobuf::int32 DescriptorProto_ExtensionRange::start() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.start)
+ return start_;
+}
+ void DescriptorProto_ExtensionRange::set_start(::google::protobuf::int32 value) {
+ set_has_start();
+ start_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.start)
+}
+
+// optional int32 end = 2;
+bool DescriptorProto_ExtensionRange::has_end() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void DescriptorProto_ExtensionRange::set_has_end() {
+ _has_bits_[0] |= 0x00000002u;
+}
+void DescriptorProto_ExtensionRange::clear_has_end() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+void DescriptorProto_ExtensionRange::clear_end() {
+ end_ = 0;
+ clear_has_end();
+}
+ ::google::protobuf::int32 DescriptorProto_ExtensionRange::end() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.end)
+ return end_;
+}
+ void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 value) {
+ set_has_end();
+ end_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.end)
+}
+
+// -------------------------------------------------------------------
+
+// DescriptorProto_ReservedRange
+
+// optional int32 start = 1;
+bool DescriptorProto_ReservedRange::has_start() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void DescriptorProto_ReservedRange::set_has_start() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void DescriptorProto_ReservedRange::clear_has_start() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void DescriptorProto_ReservedRange::clear_start() {
+ start_ = 0;
+ clear_has_start();
+}
+ ::google::protobuf::int32 DescriptorProto_ReservedRange::start() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.start)
+ return start_;
+}
+ void DescriptorProto_ReservedRange::set_start(::google::protobuf::int32 value) {
+ set_has_start();
+ start_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.start)
+}
+
+// optional int32 end = 2;
+bool DescriptorProto_ReservedRange::has_end() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void DescriptorProto_ReservedRange::set_has_end() {
+ _has_bits_[0] |= 0x00000002u;
+}
+void DescriptorProto_ReservedRange::clear_has_end() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+void DescriptorProto_ReservedRange::clear_end() {
+ end_ = 0;
+ clear_has_end();
+}
+ ::google::protobuf::int32 DescriptorProto_ReservedRange::end() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.end)
+ return end_;
+}
+ void DescriptorProto_ReservedRange::set_end(::google::protobuf::int32 value) {
+ set_has_end();
+ end_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.end)
+}
+
+// -------------------------------------------------------------------
+
+// DescriptorProto
+
+// optional string name = 1;
+bool DescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void DescriptorProto::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void DescriptorProto::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void DescriptorProto::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& DescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void DescriptorProto::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.name)
+}
+ void DescriptorProto::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.name)
+}
+ void DescriptorProto::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.name)
+}
+ ::std::string* DescriptorProto::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* DescriptorProto::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void DescriptorProto::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.name)
+}
+
+// repeated .google.protobuf.FieldDescriptorProto field = 2;
+int DescriptorProto::field_size() const {
+ return field_.size();
+}
+void DescriptorProto::clear_field() {
+ field_.Clear();
+}
+ const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.field)
+ return field_.Get(index);
+}
+ ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_field(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.field)
+ return field_.Mutable(index);
+}
+ ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() {
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field)
+ return field_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::field() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field)
+ return field_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+DescriptorProto::mutable_field() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field)
+ return &field_;
+}
+
+// repeated .google.protobuf.FieldDescriptorProto extension = 6;
+int DescriptorProto::extension_size() const {
+ return extension_.size();
+}
+void DescriptorProto::clear_extension() {
+ extension_.Clear();
+}
+ const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension)
+ return extension_.Get(index);
+}
+ ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_extension(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension)
+ return extension_.Mutable(index);
+}
+ ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension() {
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension)
+ return extension_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::extension() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension)
+ return extension_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+DescriptorProto::mutable_extension() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension)
+ return &extension_;
+}
+
+// repeated .google.protobuf.DescriptorProto nested_type = 3;
+int DescriptorProto::nested_type_size() const {
+ return nested_type_.size();
+}
+void DescriptorProto::clear_nested_type() {
+ nested_type_.Clear();
+}
+ const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.nested_type)
+ return nested_type_.Get(index);
+}
+ ::google::protobuf::DescriptorProto* DescriptorProto::mutable_nested_type(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.nested_type)
+ return nested_type_.Mutable(index);
+}
+ ::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() {
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type)
+ return nested_type_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+DescriptorProto::nested_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type)
+ return nested_type_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+DescriptorProto::mutable_nested_type() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type)
+ return &nested_type_;
+}
+
+// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
+int DescriptorProto::enum_type_size() const {
+ return enum_type_.size();
+}
+void DescriptorProto::clear_enum_type() {
+ enum_type_.Clear();
+}
+ const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.enum_type)
+ return enum_type_.Get(index);
+}
+ ::google::protobuf::EnumDescriptorProto* DescriptorProto::mutable_enum_type(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.enum_type)
+ return enum_type_.Mutable(index);
+}
+ ::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() {
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type)
+ return enum_type_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+DescriptorProto::enum_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type)
+ return enum_type_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+DescriptorProto::mutable_enum_type() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type)
+ return &enum_type_;
+}
+
+// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
+int DescriptorProto::extension_range_size() const {
+ return extension_range_.size();
+}
+void DescriptorProto::clear_extension_range() {
+ extension_range_.Clear();
+}
+ const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension_range)
+ return extension_range_.Get(index);
+}
+ ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::mutable_extension_range(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension_range)
+ return extension_range_.Mutable(index);
+}
+ ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() {
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range)
+ return extension_range_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+DescriptorProto::extension_range() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range)
+ return extension_range_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
+DescriptorProto::mutable_extension_range() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension_range)
+ return &extension_range_;
+}
+
+// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
+int DescriptorProto::oneof_decl_size() const {
+ return oneof_decl_.size();
+}
+void DescriptorProto::clear_oneof_decl() {
+ oneof_decl_.Clear();
+}
+ const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.oneof_decl)
+ return oneof_decl_.Get(index);
+}
+ ::google::protobuf::OneofDescriptorProto* DescriptorProto::mutable_oneof_decl(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.oneof_decl)
+ return oneof_decl_.Mutable(index);
+}
+ ::google::protobuf::OneofDescriptorProto* DescriptorProto::add_oneof_decl() {
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl)
+ return oneof_decl_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
+DescriptorProto::oneof_decl() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl)
+ return oneof_decl_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
+DescriptorProto::mutable_oneof_decl() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl)
+ return &oneof_decl_;
+}
+
+// optional .google.protobuf.MessageOptions options = 7;
+bool DescriptorProto::has_options() const {
+ return (_has_bits_[0] & 0x00000080u) != 0;
+}
+void DescriptorProto::set_has_options() {
+ _has_bits_[0] |= 0x00000080u;
+}
+void DescriptorProto::clear_has_options() {
+ _has_bits_[0] &= ~0x00000080u;
+}
+void DescriptorProto::clear_options() {
+ if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear();
+ clear_has_options();
+}
+ const ::google::protobuf::MessageOptions& DescriptorProto::options() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options)
+ return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() {
+ set_has_options();
+ if (options_ == NULL) {
+ options_ = new ::google::protobuf::MessageOptions;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options)
+ return options_;
+}
+ ::google::protobuf::MessageOptions* DescriptorProto::release_options() {
+ clear_has_options();
+ ::google::protobuf::MessageOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+}
+ void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options)
+}
+
+// repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+int DescriptorProto::reserved_range_size() const {
+ return reserved_range_.size();
+}
+void DescriptorProto::clear_reserved_range() {
+ reserved_range_.Clear();
+}
+ const ::google::protobuf::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_.Get(index);
+}
+ ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::mutable_reserved_range(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_.Mutable(index);
+}
+ ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() {
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
+DescriptorProto::reserved_range() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
+DescriptorProto::mutable_reserved_range() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_range)
+ return &reserved_range_;
+}
+
+// repeated string reserved_name = 10;
+int DescriptorProto::reserved_name_size() const {
+ return reserved_name_.size();
+}
+void DescriptorProto::clear_reserved_name() {
+ reserved_name_.Clear();
+}
+ const ::std::string& DescriptorProto::reserved_name(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_name)
+ return reserved_name_.Get(index);
+}
+ ::std::string* DescriptorProto::mutable_reserved_name(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_name)
+ return reserved_name_.Mutable(index);
+}
+ void DescriptorProto::set_reserved_name(int index, const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name)
+ reserved_name_.Mutable(index)->assign(value);
+}
+ void DescriptorProto::set_reserved_name(int index, const char* value) {
+ reserved_name_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.reserved_name)
+}
+ void DescriptorProto::set_reserved_name(int index, const char* value, size_t size) {
+ reserved_name_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.reserved_name)
+}
+ ::std::string* DescriptorProto::add_reserved_name() {
+ return reserved_name_.Add();
+}
+ void DescriptorProto::add_reserved_name(const ::std::string& value) {
+ reserved_name_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name)
+}
+ void DescriptorProto::add_reserved_name(const char* value) {
+ reserved_name_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.DescriptorProto.reserved_name)
+}
+ void DescriptorProto::add_reserved_name(const char* value, size_t size) {
+ reserved_name_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.DescriptorProto.reserved_name)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+DescriptorProto::reserved_name() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_name)
+ return reserved_name_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+DescriptorProto::mutable_reserved_name() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_name)
+ return &reserved_name_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -2686,7 +4113,7 @@ const int FieldDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
FieldDescriptorProto::FieldDescriptorProto()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FieldDescriptorProto)
}
@@ -2759,7 +4186,7 @@ FieldDescriptorProto* FieldDescriptorProto::New(::google::protobuf::Arena* arena
}
void FieldDescriptorProto::Clear() {
- if (_has_bits_[0 / 32] & 255) {
+ if (_has_bits_[0 / 32] & 255u) {
if (has_name()) {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -3133,7 +4560,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
int FieldDescriptorProto::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & 255) {
+ if (_has_bits_[0 / 32] & 255u) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -3209,9 +4636,9 @@ int FieldDescriptorProto::ByteSize() const {
void FieldDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const FieldDescriptorProto* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const FieldDescriptorProto*>(
- &from);
+ const FieldDescriptorProto* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const FieldDescriptorProto>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -3308,6 +4735,363 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FieldDescriptorProto
+
+// optional string name = 1;
+bool FieldDescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void FieldDescriptorProto::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void FieldDescriptorProto::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void FieldDescriptorProto::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& FieldDescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.name)
+}
+ void FieldDescriptorProto::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.name)
+}
+ void FieldDescriptorProto::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.name)
+}
+ ::std::string* FieldDescriptorProto::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name)
+}
+
+// optional int32 number = 3;
+bool FieldDescriptorProto::has_number() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void FieldDescriptorProto::set_has_number() {
+ _has_bits_[0] |= 0x00000002u;
+}
+void FieldDescriptorProto::clear_has_number() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+void FieldDescriptorProto::clear_number() {
+ number_ = 0;
+ clear_has_number();
+}
+ ::google::protobuf::int32 FieldDescriptorProto::number() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.number)
+ return number_;
+}
+ void FieldDescriptorProto::set_number(::google::protobuf::int32 value) {
+ set_has_number();
+ number_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.number)
+}
+
+// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
+bool FieldDescriptorProto::has_label() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void FieldDescriptorProto::set_has_label() {
+ _has_bits_[0] |= 0x00000004u;
+}
+void FieldDescriptorProto::clear_has_label() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+void FieldDescriptorProto::clear_label() {
+ label_ = 1;
+ clear_has_label();
+}
+ ::google::protobuf::FieldDescriptorProto_Label FieldDescriptorProto::label() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.label)
+ return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_);
+}
+ void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) {
+ assert(::google::protobuf::FieldDescriptorProto_Label_IsValid(value));
+ set_has_label();
+ label_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.label)
+}
+
+// optional .google.protobuf.FieldDescriptorProto.Type type = 5;
+bool FieldDescriptorProto::has_type() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void FieldDescriptorProto::set_has_type() {
+ _has_bits_[0] |= 0x00000008u;
+}
+void FieldDescriptorProto::clear_has_type() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+void FieldDescriptorProto::clear_type() {
+ type_ = 1;
+ clear_has_type();
+}
+ ::google::protobuf::FieldDescriptorProto_Type FieldDescriptorProto::type() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type)
+ return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_);
+}
+ void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) {
+ assert(::google::protobuf::FieldDescriptorProto_Type_IsValid(value));
+ set_has_type();
+ type_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type)
+}
+
+// optional string type_name = 6;
+bool FieldDescriptorProto::has_type_name() const {
+ return (_has_bits_[0] & 0x00000010u) != 0;
+}
+void FieldDescriptorProto::set_has_type_name() {
+ _has_bits_[0] |= 0x00000010u;
+}
+void FieldDescriptorProto::clear_has_type_name() {
+ _has_bits_[0] &= ~0x00000010u;
+}
+void FieldDescriptorProto::clear_type_name() {
+ type_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_type_name();
+}
+ const ::std::string& FieldDescriptorProto::type_name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type_name)
+ return type_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_type_name(const ::std::string& value) {
+ set_has_type_name();
+ type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type_name)
+}
+ void FieldDescriptorProto::set_type_name(const char* value) {
+ set_has_type_name();
+ type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.type_name)
+}
+ void FieldDescriptorProto::set_type_name(const char* value, size_t size) {
+ set_has_type_name();
+ type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.type_name)
+}
+ ::std::string* FieldDescriptorProto::mutable_type_name() {
+ set_has_type_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.type_name)
+ return type_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_type_name() {
+ clear_has_type_name();
+ return type_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_type_name(::std::string* type_name) {
+ if (type_name != NULL) {
+ set_has_type_name();
+ } else {
+ clear_has_type_name();
+ }
+ type_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.type_name)
+}
+
+// optional string extendee = 2;
+bool FieldDescriptorProto::has_extendee() const {
+ return (_has_bits_[0] & 0x00000020u) != 0;
+}
+void FieldDescriptorProto::set_has_extendee() {
+ _has_bits_[0] |= 0x00000020u;
+}
+void FieldDescriptorProto::clear_has_extendee() {
+ _has_bits_[0] &= ~0x00000020u;
+}
+void FieldDescriptorProto::clear_extendee() {
+ extendee_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_extendee();
+}
+ const ::std::string& FieldDescriptorProto::extendee() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.extendee)
+ return extendee_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_extendee(const ::std::string& value) {
+ set_has_extendee();
+ extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.extendee)
+}
+ void FieldDescriptorProto::set_extendee(const char* value) {
+ set_has_extendee();
+ extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.extendee)
+}
+ void FieldDescriptorProto::set_extendee(const char* value, size_t size) {
+ set_has_extendee();
+ extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.extendee)
+}
+ ::std::string* FieldDescriptorProto::mutable_extendee() {
+ set_has_extendee();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.extendee)
+ return extendee_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_extendee() {
+ clear_has_extendee();
+ return extendee_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee) {
+ if (extendee != NULL) {
+ set_has_extendee();
+ } else {
+ clear_has_extendee();
+ }
+ extendee_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), extendee);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee)
+}
+
+// optional string default_value = 7;
+bool FieldDescriptorProto::has_default_value() const {
+ return (_has_bits_[0] & 0x00000040u) != 0;
+}
+void FieldDescriptorProto::set_has_default_value() {
+ _has_bits_[0] |= 0x00000040u;
+}
+void FieldDescriptorProto::clear_has_default_value() {
+ _has_bits_[0] &= ~0x00000040u;
+}
+void FieldDescriptorProto::clear_default_value() {
+ default_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_default_value();
+}
+ const ::std::string& FieldDescriptorProto::default_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.default_value)
+ return default_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_default_value(const ::std::string& value) {
+ set_has_default_value();
+ default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.default_value)
+}
+ void FieldDescriptorProto::set_default_value(const char* value) {
+ set_has_default_value();
+ default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.default_value)
+}
+ void FieldDescriptorProto::set_default_value(const char* value, size_t size) {
+ set_has_default_value();
+ default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.default_value)
+}
+ ::std::string* FieldDescriptorProto::mutable_default_value() {
+ set_has_default_value();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.default_value)
+ return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_default_value() {
+ clear_has_default_value();
+ return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_default_value(::std::string* default_value) {
+ if (default_value != NULL) {
+ set_has_default_value();
+ } else {
+ clear_has_default_value();
+ }
+ default_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), default_value);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.default_value)
+}
+
+// optional int32 oneof_index = 9;
+bool FieldDescriptorProto::has_oneof_index() const {
+ return (_has_bits_[0] & 0x00000080u) != 0;
+}
+void FieldDescriptorProto::set_has_oneof_index() {
+ _has_bits_[0] |= 0x00000080u;
+}
+void FieldDescriptorProto::clear_has_oneof_index() {
+ _has_bits_[0] &= ~0x00000080u;
+}
+void FieldDescriptorProto::clear_oneof_index() {
+ oneof_index_ = 0;
+ clear_has_oneof_index();
+}
+ ::google::protobuf::int32 FieldDescriptorProto::oneof_index() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.oneof_index)
+ return oneof_index_;
+}
+ void FieldDescriptorProto::set_oneof_index(::google::protobuf::int32 value) {
+ set_has_oneof_index();
+ oneof_index_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index)
+}
+
+// optional .google.protobuf.FieldOptions options = 8;
+bool FieldDescriptorProto::has_options() const {
+ return (_has_bits_[0] & 0x00000100u) != 0;
+}
+void FieldDescriptorProto::set_has_options() {
+ _has_bits_[0] |= 0x00000100u;
+}
+void FieldDescriptorProto::clear_has_options() {
+ _has_bits_[0] &= ~0x00000100u;
+}
+void FieldDescriptorProto::clear_options() {
+ if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
+ clear_has_options();
+}
+ const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options)
+ return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() {
+ set_has_options();
+ if (options_ == NULL) {
+ options_ = new ::google::protobuf::FieldOptions;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options)
+ return options_;
+}
+ ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() {
+ clear_has_options();
+ ::google::protobuf::FieldOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+}
+ void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.options)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -3316,7 +5100,7 @@ const int OneofDescriptorProto::kNameFieldNumber;
#endif // !_MSC_VER
OneofDescriptorProto::OneofDescriptorProto()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.OneofDescriptorProto)
}
@@ -3498,9 +5282,9 @@ int OneofDescriptorProto::ByteSize() const {
void OneofDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const OneofDescriptorProto* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const OneofDescriptorProto*>(
- &from);
+ const OneofDescriptorProto* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const OneofDescriptorProto>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -3557,6 +5341,63 @@ void OneofDescriptorProto::InternalSwap(OneofDescriptorProto* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// OneofDescriptorProto
+
+// optional string name = 1;
+bool OneofDescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void OneofDescriptorProto::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void OneofDescriptorProto::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void OneofDescriptorProto::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& OneofDescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void OneofDescriptorProto::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.OneofDescriptorProto.name)
+}
+ void OneofDescriptorProto::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.OneofDescriptorProto.name)
+}
+ void OneofDescriptorProto::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.OneofDescriptorProto.name)
+}
+ ::std::string* OneofDescriptorProto::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* OneofDescriptorProto::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void OneofDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.name)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -3567,7 +5408,7 @@ const int EnumDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
EnumDescriptorProto::EnumDescriptorProto()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.EnumDescriptorProto)
}
@@ -3630,7 +5471,7 @@ EnumDescriptorProto* EnumDescriptorProto::New(::google::protobuf::Arena* arena)
}
void EnumDescriptorProto::Clear() {
- if (_has_bits_[0 / 32] & 5) {
+ if (_has_bits_[0 / 32] & 5u) {
if (has_name()) {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -3675,12 +5516,15 @@ bool EnumDescriptorProto::MergePartialFromCodedStream(
case 2: {
if (tag == 18) {
parse_value:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_value:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_value()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(18)) goto parse_value;
+ if (input->ExpectTag(18)) goto parse_loop_value;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectTag(26)) goto parse_options;
break;
}
@@ -3791,7 +5635,7 @@ void EnumDescriptorProto::SerializeWithCachedSizes(
int EnumDescriptorProto::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & 5) {
+ if (_has_bits_[0 / 32] & 5u) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -3828,9 +5672,9 @@ int EnumDescriptorProto::ByteSize() const {
void EnumDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const EnumDescriptorProto* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const EnumDescriptorProto*>(
- &from);
+ const EnumDescriptorProto* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const EnumDescriptorProto>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -3897,6 +5741,136 @@ void EnumDescriptorProto::InternalSwap(EnumDescriptorProto* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumDescriptorProto
+
+// optional string name = 1;
+bool EnumDescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void EnumDescriptorProto::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void EnumDescriptorProto::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void EnumDescriptorProto::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& EnumDescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumDescriptorProto::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.name)
+}
+ void EnumDescriptorProto::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.name)
+}
+ void EnumDescriptorProto::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.name)
+}
+ ::std::string* EnumDescriptorProto::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* EnumDescriptorProto::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name)
+}
+
+// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
+int EnumDescriptorProto::value_size() const {
+ return value_.size();
+}
+void EnumDescriptorProto::clear_value() {
+ value_.Clear();
+}
+ const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.value)
+ return value_.Get(index);
+}
+ ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::mutable_value(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.value)
+ return value_.Mutable(index);
+}
+ ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_value() {
+ // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value)
+ return value_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+EnumDescriptorProto::value() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value)
+ return value_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
+EnumDescriptorProto::mutable_value() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value)
+ return &value_;
+}
+
+// optional .google.protobuf.EnumOptions options = 3;
+bool EnumDescriptorProto::has_options() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void EnumDescriptorProto::set_has_options() {
+ _has_bits_[0] |= 0x00000004u;
+}
+void EnumDescriptorProto::clear_has_options() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+void EnumDescriptorProto::clear_options() {
+ if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear();
+ clear_has_options();
+}
+ const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options)
+ return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() {
+ set_has_options();
+ if (options_ == NULL) {
+ options_ = new ::google::protobuf::EnumOptions;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options)
+ return options_;
+}
+ ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() {
+ clear_has_options();
+ ::google::protobuf::EnumOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+}
+ void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.options)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -3907,7 +5881,7 @@ const int EnumValueDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
EnumValueDescriptorProto::EnumValueDescriptorProto()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.EnumValueDescriptorProto)
}
@@ -3971,7 +5945,7 @@ EnumValueDescriptorProto* EnumValueDescriptorProto::New(::google::protobuf::Aren
}
void EnumValueDescriptorProto::Clear() {
- if (_has_bits_[0 / 32] & 7) {
+ if (_has_bits_[0 / 32] & 7u) {
if (has_name()) {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -4130,7 +6104,7 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes(
int EnumValueDescriptorProto::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & 7) {
+ if (_has_bits_[0 / 32] & 7u) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -4166,9 +6140,9 @@ int EnumValueDescriptorProto::ByteSize() const {
void EnumValueDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const EnumValueDescriptorProto* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const EnumValueDescriptorProto*>(
- &from);
+ const EnumValueDescriptorProto* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const EnumValueDescriptorProto>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -4236,6 +6210,130 @@ void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumValueDescriptorProto
+
+// optional string name = 1;
+bool EnumValueDescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void EnumValueDescriptorProto::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void EnumValueDescriptorProto::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void EnumValueDescriptorProto::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& EnumValueDescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumValueDescriptorProto::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.name)
+}
+ void EnumValueDescriptorProto::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValueDescriptorProto.name)
+}
+ void EnumValueDescriptorProto::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValueDescriptorProto.name)
+}
+ ::std::string* EnumValueDescriptorProto::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* EnumValueDescriptorProto::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumValueDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name)
+}
+
+// optional int32 number = 2;
+bool EnumValueDescriptorProto::has_number() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void EnumValueDescriptorProto::set_has_number() {
+ _has_bits_[0] |= 0x00000002u;
+}
+void EnumValueDescriptorProto::clear_has_number() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+void EnumValueDescriptorProto::clear_number() {
+ number_ = 0;
+ clear_has_number();
+}
+ ::google::protobuf::int32 EnumValueDescriptorProto::number() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.number)
+ return number_;
+}
+ void EnumValueDescriptorProto::set_number(::google::protobuf::int32 value) {
+ set_has_number();
+ number_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.number)
+}
+
+// optional .google.protobuf.EnumValueOptions options = 3;
+bool EnumValueDescriptorProto::has_options() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void EnumValueDescriptorProto::set_has_options() {
+ _has_bits_[0] |= 0x00000004u;
+}
+void EnumValueDescriptorProto::clear_has_options() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+void EnumValueDescriptorProto::clear_options() {
+ if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear();
+ clear_has_options();
+}
+ const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options)
+ return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() {
+ set_has_options();
+ if (options_ == NULL) {
+ options_ = new ::google::protobuf::EnumValueOptions;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options)
+ return options_;
+}
+ ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() {
+ clear_has_options();
+ ::google::protobuf::EnumValueOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+}
+ void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.options)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -4246,7 +6344,7 @@ const int ServiceDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
ServiceDescriptorProto::ServiceDescriptorProto()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.ServiceDescriptorProto)
}
@@ -4309,7 +6407,7 @@ ServiceDescriptorProto* ServiceDescriptorProto::New(::google::protobuf::Arena* a
}
void ServiceDescriptorProto::Clear() {
- if (_has_bits_[0 / 32] & 5) {
+ if (_has_bits_[0 / 32] & 5u) {
if (has_name()) {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -4354,12 +6452,15 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream(
case 2: {
if (tag == 18) {
parse_method:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_method:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_method()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(18)) goto parse_method;
+ if (input->ExpectTag(18)) goto parse_loop_method;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectTag(26)) goto parse_options;
break;
}
@@ -4470,7 +6571,7 @@ void ServiceDescriptorProto::SerializeWithCachedSizes(
int ServiceDescriptorProto::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & 5) {
+ if (_has_bits_[0 / 32] & 5u) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -4507,9 +6608,9 @@ int ServiceDescriptorProto::ByteSize() const {
void ServiceDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const ServiceDescriptorProto* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const ServiceDescriptorProto*>(
- &from);
+ const ServiceDescriptorProto* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const ServiceDescriptorProto>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -4576,6 +6677,136 @@ void ServiceDescriptorProto::InternalSwap(ServiceDescriptorProto* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// ServiceDescriptorProto
+
+// optional string name = 1;
+bool ServiceDescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void ServiceDescriptorProto::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void ServiceDescriptorProto::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void ServiceDescriptorProto::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& ServiceDescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void ServiceDescriptorProto::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.ServiceDescriptorProto.name)
+}
+ void ServiceDescriptorProto::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.ServiceDescriptorProto.name)
+}
+ void ServiceDescriptorProto::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.ServiceDescriptorProto.name)
+}
+ ::std::string* ServiceDescriptorProto::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* ServiceDescriptorProto::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void ServiceDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.name)
+}
+
+// repeated .google.protobuf.MethodDescriptorProto method = 2;
+int ServiceDescriptorProto::method_size() const {
+ return method_.size();
+}
+void ServiceDescriptorProto::clear_method() {
+ method_.Clear();
+}
+ const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.method)
+ return method_.Get(index);
+}
+ ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::mutable_method(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.method)
+ return method_.Mutable(index);
+}
+ ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_method() {
+ // @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method)
+ return method_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ServiceDescriptorProto::method() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method)
+ return method_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
+ServiceDescriptorProto::mutable_method() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method)
+ return &method_;
+}
+
+// optional .google.protobuf.ServiceOptions options = 3;
+bool ServiceDescriptorProto::has_options() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void ServiceDescriptorProto::set_has_options() {
+ _has_bits_[0] |= 0x00000004u;
+}
+void ServiceDescriptorProto::clear_has_options() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+void ServiceDescriptorProto::clear_options() {
+ if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear();
+ clear_has_options();
+}
+ const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options)
+ return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() {
+ set_has_options();
+ if (options_ == NULL) {
+ options_ = new ::google::protobuf::ServiceOptions;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options)
+ return options_;
+}
+ ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() {
+ clear_has_options();
+ ::google::protobuf::ServiceOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+}
+ void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.options)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -4589,7 +6820,7 @@ const int MethodDescriptorProto::kServerStreamingFieldNumber;
#endif // !_MSC_VER
MethodDescriptorProto::MethodDescriptorProto()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.MethodDescriptorProto)
}
@@ -4658,17 +6889,15 @@ MethodDescriptorProto* MethodDescriptorProto::New(::google::protobuf::Arena* are
}
void MethodDescriptorProto::Clear() {
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
- &reinterpret_cast<MethodDescriptorProto*>(16)->f) - \
- reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<MethodDescriptorProto*>(16)->f)
-#define ZR_(first, last) do { \
- size_t f = OFFSET_OF_FIELD_(first); \
- size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \
- ::memset(&first, 0, n); \
- } while (0)
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
- if (_has_bits_[0 / 32] & 63) {
+ if (_has_bits_[0 / 32] & 63u) {
ZR_(client_streaming_, server_streaming_);
if (has_name()) {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@@ -4684,7 +6913,7 @@ void MethodDescriptorProto::Clear() {
}
}
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
#undef ZR_
::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -4938,7 +7167,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
int MethodDescriptorProto::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & 63) {
+ if (_has_bits_[0 / 32] & 63u) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -4991,9 +7220,9 @@ int MethodDescriptorProto::ByteSize() const {
void MethodDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const MethodDescriptorProto* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const MethodDescriptorProto*>(
- &from);
+ const MethodDescriptorProto* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const MethodDescriptorProto>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -5075,6 +7304,260 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// MethodDescriptorProto
+
+// optional string name = 1;
+bool MethodDescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void MethodDescriptorProto::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void MethodDescriptorProto::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void MethodDescriptorProto::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& MethodDescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.name)
+}
+ void MethodDescriptorProto::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.name)
+}
+ void MethodDescriptorProto::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.name)
+}
+ ::std::string* MethodDescriptorProto::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* MethodDescriptorProto::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name)
+}
+
+// optional string input_type = 2;
+bool MethodDescriptorProto::has_input_type() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void MethodDescriptorProto::set_has_input_type() {
+ _has_bits_[0] |= 0x00000002u;
+}
+void MethodDescriptorProto::clear_has_input_type() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+void MethodDescriptorProto::clear_input_type() {
+ input_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_input_type();
+}
+ const ::std::string& MethodDescriptorProto::input_type() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.input_type)
+ return input_type_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_input_type(const ::std::string& value) {
+ set_has_input_type();
+ input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.input_type)
+}
+ void MethodDescriptorProto::set_input_type(const char* value) {
+ set_has_input_type();
+ input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.input_type)
+}
+ void MethodDescriptorProto::set_input_type(const char* value, size_t size) {
+ set_has_input_type();
+ input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.input_type)
+}
+ ::std::string* MethodDescriptorProto::mutable_input_type() {
+ set_has_input_type();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.input_type)
+ return input_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* MethodDescriptorProto::release_input_type() {
+ clear_has_input_type();
+ return input_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_allocated_input_type(::std::string* input_type) {
+ if (input_type != NULL) {
+ set_has_input_type();
+ } else {
+ clear_has_input_type();
+ }
+ input_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), input_type);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.input_type)
+}
+
+// optional string output_type = 3;
+bool MethodDescriptorProto::has_output_type() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void MethodDescriptorProto::set_has_output_type() {
+ _has_bits_[0] |= 0x00000004u;
+}
+void MethodDescriptorProto::clear_has_output_type() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+void MethodDescriptorProto::clear_output_type() {
+ output_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_output_type();
+}
+ const ::std::string& MethodDescriptorProto::output_type() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.output_type)
+ return output_type_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_output_type(const ::std::string& value) {
+ set_has_output_type();
+ output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.output_type)
+}
+ void MethodDescriptorProto::set_output_type(const char* value) {
+ set_has_output_type();
+ output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.output_type)
+}
+ void MethodDescriptorProto::set_output_type(const char* value, size_t size) {
+ set_has_output_type();
+ output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.output_type)
+}
+ ::std::string* MethodDescriptorProto::mutable_output_type() {
+ set_has_output_type();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.output_type)
+ return output_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* MethodDescriptorProto::release_output_type() {
+ clear_has_output_type();
+ return output_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_allocated_output_type(::std::string* output_type) {
+ if (output_type != NULL) {
+ set_has_output_type();
+ } else {
+ clear_has_output_type();
+ }
+ output_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), output_type);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.output_type)
+}
+
+// optional .google.protobuf.MethodOptions options = 4;
+bool MethodDescriptorProto::has_options() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void MethodDescriptorProto::set_has_options() {
+ _has_bits_[0] |= 0x00000008u;
+}
+void MethodDescriptorProto::clear_has_options() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+void MethodDescriptorProto::clear_options() {
+ if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear();
+ clear_has_options();
+}
+ const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options)
+ return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() {
+ set_has_options();
+ if (options_ == NULL) {
+ options_ = new ::google::protobuf::MethodOptions;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options)
+ return options_;
+}
+ ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() {
+ clear_has_options();
+ ::google::protobuf::MethodOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+}
+ void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.options)
+}
+
+// optional bool client_streaming = 5 [default = false];
+bool MethodDescriptorProto::has_client_streaming() const {
+ return (_has_bits_[0] & 0x00000010u) != 0;
+}
+void MethodDescriptorProto::set_has_client_streaming() {
+ _has_bits_[0] |= 0x00000010u;
+}
+void MethodDescriptorProto::clear_has_client_streaming() {
+ _has_bits_[0] &= ~0x00000010u;
+}
+void MethodDescriptorProto::clear_client_streaming() {
+ client_streaming_ = false;
+ clear_has_client_streaming();
+}
+ bool MethodDescriptorProto::client_streaming() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.client_streaming)
+ return client_streaming_;
+}
+ void MethodDescriptorProto::set_client_streaming(bool value) {
+ set_has_client_streaming();
+ client_streaming_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.client_streaming)
+}
+
+// optional bool server_streaming = 6 [default = false];
+bool MethodDescriptorProto::has_server_streaming() const {
+ return (_has_bits_[0] & 0x00000020u) != 0;
+}
+void MethodDescriptorProto::set_has_server_streaming() {
+ _has_bits_[0] |= 0x00000020u;
+}
+void MethodDescriptorProto::clear_has_server_streaming() {
+ _has_bits_[0] &= ~0x00000020u;
+}
+void MethodDescriptorProto::clear_server_streaming() {
+ server_streaming_ = false;
+ clear_has_server_streaming();
+}
+ bool MethodDescriptorProto::server_streaming() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.server_streaming)
+ return server_streaming_;
+}
+ void MethodDescriptorProto::set_server_streaming(bool value) {
+ set_has_server_streaming();
+ server_streaming_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.server_streaming)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -5114,11 +7597,14 @@ const int FileOptions::kJavaGenericServicesFieldNumber;
const int FileOptions::kPyGenericServicesFieldNumber;
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 // !_MSC_VER
FileOptions::FileOptions()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FileOptions)
}
@@ -5149,6 +7635,9 @@ void FileOptions::SharedCtor() {
py_generic_services_ = false;
deprecated_ = false;
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_));
}
@@ -5161,6 +7650,8 @@ void FileOptions::SharedDtor() {
java_package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
java_outer_classname_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
go_package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ objc_class_prefix_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ csharp_namespace_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (this != default_instance_) {
}
}
@@ -5192,17 +7683,15 @@ FileOptions* FileOptions::New(::google::protobuf::Arena* arena) const {
void FileOptions::Clear() {
_extensions_.Clear();
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
- &reinterpret_cast<FileOptions*>(16)->f) - \
- reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<FileOptions*>(16)->f)
-#define ZR_(first, last) do { \
- size_t f = OFFSET_OF_FIELD_(first); \
- size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \
- ::memset(&first, 0, n); \
- } while (0)
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
- if (_has_bits_[0 / 32] & 255) {
+ if (_has_bits_[0 / 32] & 255u) {
ZR_(java_multiple_files_, cc_generic_services_);
if (has_java_package()) {
java_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@@ -5215,9 +7704,17 @@ void FileOptions::Clear() {
go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
}
- ZR_(java_generic_services_, cc_enable_arenas_);
+ if (_has_bits_[8 / 32] & 32512u) {
+ ZR_(java_generic_services_, javanano_use_deprecated_package_);
+ if (has_objc_class_prefix()) {
+ objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ if (has_csharp_namespace()) {
+ csharp_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ }
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
#undef ZR_
uninterpreted_option_.Clear();
@@ -5423,6 +7920,55 @@ bool FileOptions::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
+ if (input->ExpectTag(290)) goto parse_objc_class_prefix;
+ break;
+ }
+
+ // optional string objc_class_prefix = 36;
+ case 36: {
+ if (tag == 290) {
+ parse_objc_class_prefix:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_objc_class_prefix()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->objc_class_prefix().data(), this->objc_class_prefix().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.FileOptions.objc_class_prefix");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(298)) goto parse_csharp_namespace;
+ break;
+ }
+
+ // optional string csharp_namespace = 37;
+ case 37: {
+ if (tag == 298) {
+ parse_csharp_namespace:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_csharp_namespace()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->csharp_namespace().data(), this->csharp_namespace().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.FileOptions.csharp_namespace");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(304)) goto parse_javanano_use_deprecated_package;
+ break;
+ }
+
+ // optional bool javanano_use_deprecated_package = 38;
+ 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;
}
@@ -5431,12 +7977,15 @@ bool FileOptions::MergePartialFromCodedStream(
case 999: {
if (tag == 7994) {
parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_uninterpreted_option()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+ if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -5547,6 +8096,31 @@ void FileOptions::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteBool(31, this->cc_enable_arenas(), output);
}
+ // optional string objc_class_prefix = 36;
+ if (has_objc_class_prefix()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->objc_class_prefix().data(), this->objc_class_prefix().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.FileOptions.objc_class_prefix");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 36, this->objc_class_prefix(), output);
+ }
+
+ // optional string csharp_namespace = 37;
+ if (has_csharp_namespace()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->csharp_namespace().data(), this->csharp_namespace().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.FileOptions.csharp_namespace");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 37, this->csharp_namespace(), output);
+ }
+
+ // optional bool javanano_use_deprecated_package = 38;
+ 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(
@@ -5646,6 +8220,33 @@ void FileOptions::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(31, this->cc_enable_arenas(), target);
}
+ // optional string objc_class_prefix = 36;
+ if (has_objc_class_prefix()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->objc_class_prefix().data(), this->objc_class_prefix().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.FileOptions.objc_class_prefix");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 36, this->objc_class_prefix(), target);
+ }
+
+ // optional string csharp_namespace = 37;
+ if (has_csharp_namespace()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->csharp_namespace().data(), this->csharp_namespace().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.FileOptions.csharp_namespace");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 37, this->csharp_namespace(), target);
+ }
+
+ // optional bool javanano_use_deprecated_package = 38;
+ 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::
@@ -5668,7 +8269,7 @@ void FileOptions::SerializeWithCachedSizes(
int FileOptions::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & 255) {
+ if (_has_bits_[0 / 32] & 255u) {
// optional string java_package = 1;
if (has_java_package()) {
total_size += 1 +
@@ -5717,7 +8318,7 @@ int FileOptions::ByteSize() const {
}
}
- if (_has_bits_[8 / 32] & 3840) {
+ if (_has_bits_[8 / 32] & 32512u) {
// optional bool java_generic_services = 17 [default = false];
if (has_java_generic_services()) {
total_size += 2 + 1;
@@ -5738,6 +8339,25 @@ int FileOptions::ByteSize() const {
total_size += 2 + 1;
}
+ // optional string objc_class_prefix = 36;
+ if (has_objc_class_prefix()) {
+ total_size += 2 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->objc_class_prefix());
+ }
+
+ // optional string csharp_namespace = 37;
+ if (has_csharp_namespace()) {
+ total_size += 2 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->csharp_namespace());
+ }
+
+ // optional bool javanano_use_deprecated_package = 38;
+ if (has_javanano_use_deprecated_package()) {
+ total_size += 2 + 1;
+ }
+
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
total_size += 2 * this->uninterpreted_option_size();
@@ -5762,9 +8382,9 @@ int FileOptions::ByteSize() const {
void FileOptions::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const FileOptions* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const FileOptions*>(
- &from);
+ const FileOptions* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const FileOptions>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -5817,6 +8437,17 @@ void FileOptions::MergeFrom(const FileOptions& from) {
if (from.has_cc_enable_arenas()) {
set_cc_enable_arenas(from.cc_enable_arenas());
}
+ if (from.has_objc_class_prefix()) {
+ set_has_objc_class_prefix();
+ objc_class_prefix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.objc_class_prefix_);
+ }
+ if (from.has_csharp_namespace()) {
+ 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()) {
@@ -5860,6 +8491,9 @@ void FileOptions::InternalSwap(FileOptions* other) {
std::swap(py_generic_services_, other->py_generic_services_);
std::swap(deprecated_, other->deprecated_);
std::swap(cc_enable_arenas_, other->cc_enable_arenas_);
+ objc_class_prefix_.Swap(&other->objc_class_prefix_);
+ 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_);
@@ -5875,6 +8509,546 @@ void FileOptions::InternalSwap(FileOptions* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FileOptions
+
+// optional string java_package = 1;
+bool FileOptions::has_java_package() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void FileOptions::set_has_java_package() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void FileOptions::clear_has_java_package() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void FileOptions::clear_java_package() {
+ java_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_java_package();
+}
+ const ::std::string& FileOptions::java_package() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_package)
+ return java_package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_java_package(const ::std::string& value) {
+ set_has_java_package();
+ java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_package)
+}
+ void FileOptions::set_java_package(const char* value) {
+ set_has_java_package();
+ java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_package)
+}
+ void FileOptions::set_java_package(const char* value, size_t size) {
+ set_has_java_package();
+ java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_package)
+}
+ ::std::string* FileOptions::mutable_java_package() {
+ set_has_java_package();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_package)
+ return java_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_java_package() {
+ clear_has_java_package();
+ return java_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_java_package(::std::string* java_package) {
+ if (java_package != NULL) {
+ set_has_java_package();
+ } else {
+ clear_has_java_package();
+ }
+ java_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_package);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_package)
+}
+
+// optional string java_outer_classname = 8;
+bool FileOptions::has_java_outer_classname() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void FileOptions::set_has_java_outer_classname() {
+ _has_bits_[0] |= 0x00000002u;
+}
+void FileOptions::clear_has_java_outer_classname() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+void FileOptions::clear_java_outer_classname() {
+ java_outer_classname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_java_outer_classname();
+}
+ const ::std::string& FileOptions::java_outer_classname() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_outer_classname)
+ return java_outer_classname_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_java_outer_classname(const ::std::string& value) {
+ set_has_java_outer_classname();
+ java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_outer_classname)
+}
+ void FileOptions::set_java_outer_classname(const char* value) {
+ set_has_java_outer_classname();
+ java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_outer_classname)
+}
+ void FileOptions::set_java_outer_classname(const char* value, size_t size) {
+ set_has_java_outer_classname();
+ java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_outer_classname)
+}
+ ::std::string* FileOptions::mutable_java_outer_classname() {
+ set_has_java_outer_classname();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_outer_classname)
+ return java_outer_classname_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_java_outer_classname() {
+ clear_has_java_outer_classname();
+ return java_outer_classname_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_java_outer_classname(::std::string* java_outer_classname) {
+ if (java_outer_classname != NULL) {
+ set_has_java_outer_classname();
+ } else {
+ clear_has_java_outer_classname();
+ }
+ java_outer_classname_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_outer_classname);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_outer_classname)
+}
+
+// optional bool java_multiple_files = 10 [default = false];
+bool FileOptions::has_java_multiple_files() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void FileOptions::set_has_java_multiple_files() {
+ _has_bits_[0] |= 0x00000004u;
+}
+void FileOptions::clear_has_java_multiple_files() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+void FileOptions::clear_java_multiple_files() {
+ java_multiple_files_ = false;
+ clear_has_java_multiple_files();
+}
+ bool FileOptions::java_multiple_files() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_multiple_files)
+ return java_multiple_files_;
+}
+ void FileOptions::set_java_multiple_files(bool value) {
+ set_has_java_multiple_files();
+ java_multiple_files_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_multiple_files)
+}
+
+// optional bool java_generate_equals_and_hash = 20 [default = false];
+bool FileOptions::has_java_generate_equals_and_hash() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void FileOptions::set_has_java_generate_equals_and_hash() {
+ _has_bits_[0] |= 0x00000008u;
+}
+void FileOptions::clear_has_java_generate_equals_and_hash() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+void FileOptions::clear_java_generate_equals_and_hash() {
+ java_generate_equals_and_hash_ = false;
+ clear_has_java_generate_equals_and_hash();
+}
+ bool FileOptions::java_generate_equals_and_hash() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generate_equals_and_hash)
+ return java_generate_equals_and_hash_;
+}
+ void FileOptions::set_java_generate_equals_and_hash(bool value) {
+ set_has_java_generate_equals_and_hash();
+ java_generate_equals_and_hash_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generate_equals_and_hash)
+}
+
+// optional bool java_string_check_utf8 = 27 [default = false];
+bool FileOptions::has_java_string_check_utf8() const {
+ return (_has_bits_[0] & 0x00000010u) != 0;
+}
+void FileOptions::set_has_java_string_check_utf8() {
+ _has_bits_[0] |= 0x00000010u;
+}
+void FileOptions::clear_has_java_string_check_utf8() {
+ _has_bits_[0] &= ~0x00000010u;
+}
+void FileOptions::clear_java_string_check_utf8() {
+ java_string_check_utf8_ = false;
+ clear_has_java_string_check_utf8();
+}
+ bool FileOptions::java_string_check_utf8() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_string_check_utf8)
+ return java_string_check_utf8_;
+}
+ void FileOptions::set_java_string_check_utf8(bool value) {
+ set_has_java_string_check_utf8();
+ java_string_check_utf8_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_string_check_utf8)
+}
+
+// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
+bool FileOptions::has_optimize_for() const {
+ return (_has_bits_[0] & 0x00000020u) != 0;
+}
+void FileOptions::set_has_optimize_for() {
+ _has_bits_[0] |= 0x00000020u;
+}
+void FileOptions::clear_has_optimize_for() {
+ _has_bits_[0] &= ~0x00000020u;
+}
+void FileOptions::clear_optimize_for() {
+ optimize_for_ = 1;
+ clear_has_optimize_for();
+}
+ ::google::protobuf::FileOptions_OptimizeMode FileOptions::optimize_for() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.optimize_for)
+ return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_);
+}
+ void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) {
+ assert(::google::protobuf::FileOptions_OptimizeMode_IsValid(value));
+ set_has_optimize_for();
+ optimize_for_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.optimize_for)
+}
+
+// optional string go_package = 11;
+bool FileOptions::has_go_package() const {
+ return (_has_bits_[0] & 0x00000040u) != 0;
+}
+void FileOptions::set_has_go_package() {
+ _has_bits_[0] |= 0x00000040u;
+}
+void FileOptions::clear_has_go_package() {
+ _has_bits_[0] &= ~0x00000040u;
+}
+void FileOptions::clear_go_package() {
+ go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_go_package();
+}
+ const ::std::string& FileOptions::go_package() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.go_package)
+ return go_package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_go_package(const ::std::string& value) {
+ set_has_go_package();
+ go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.go_package)
+}
+ void FileOptions::set_go_package(const char* value) {
+ set_has_go_package();
+ go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.go_package)
+}
+ void FileOptions::set_go_package(const char* value, size_t size) {
+ set_has_go_package();
+ go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.go_package)
+}
+ ::std::string* FileOptions::mutable_go_package() {
+ set_has_go_package();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.go_package)
+ return go_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_go_package() {
+ clear_has_go_package();
+ return go_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_go_package(::std::string* go_package) {
+ if (go_package != NULL) {
+ set_has_go_package();
+ } else {
+ clear_has_go_package();
+ }
+ go_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), go_package);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.go_package)
+}
+
+// optional bool cc_generic_services = 16 [default = false];
+bool FileOptions::has_cc_generic_services() const {
+ return (_has_bits_[0] & 0x00000080u) != 0;
+}
+void FileOptions::set_has_cc_generic_services() {
+ _has_bits_[0] |= 0x00000080u;
+}
+void FileOptions::clear_has_cc_generic_services() {
+ _has_bits_[0] &= ~0x00000080u;
+}
+void FileOptions::clear_cc_generic_services() {
+ cc_generic_services_ = false;
+ clear_has_cc_generic_services();
+}
+ bool FileOptions::cc_generic_services() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_generic_services)
+ return cc_generic_services_;
+}
+ void FileOptions::set_cc_generic_services(bool value) {
+ set_has_cc_generic_services();
+ cc_generic_services_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_generic_services)
+}
+
+// optional bool java_generic_services = 17 [default = false];
+bool FileOptions::has_java_generic_services() const {
+ return (_has_bits_[0] & 0x00000100u) != 0;
+}
+void FileOptions::set_has_java_generic_services() {
+ _has_bits_[0] |= 0x00000100u;
+}
+void FileOptions::clear_has_java_generic_services() {
+ _has_bits_[0] &= ~0x00000100u;
+}
+void FileOptions::clear_java_generic_services() {
+ java_generic_services_ = false;
+ clear_has_java_generic_services();
+}
+ bool FileOptions::java_generic_services() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generic_services)
+ return java_generic_services_;
+}
+ void FileOptions::set_java_generic_services(bool value) {
+ set_has_java_generic_services();
+ java_generic_services_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generic_services)
+}
+
+// optional bool py_generic_services = 18 [default = false];
+bool FileOptions::has_py_generic_services() const {
+ return (_has_bits_[0] & 0x00000200u) != 0;
+}
+void FileOptions::set_has_py_generic_services() {
+ _has_bits_[0] |= 0x00000200u;
+}
+void FileOptions::clear_has_py_generic_services() {
+ _has_bits_[0] &= ~0x00000200u;
+}
+void FileOptions::clear_py_generic_services() {
+ py_generic_services_ = false;
+ clear_has_py_generic_services();
+}
+ bool FileOptions::py_generic_services() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.py_generic_services)
+ return py_generic_services_;
+}
+ void FileOptions::set_py_generic_services(bool value) {
+ set_has_py_generic_services();
+ py_generic_services_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.py_generic_services)
+}
+
+// optional bool deprecated = 23 [default = false];
+bool FileOptions::has_deprecated() const {
+ return (_has_bits_[0] & 0x00000400u) != 0;
+}
+void FileOptions::set_has_deprecated() {
+ _has_bits_[0] |= 0x00000400u;
+}
+void FileOptions::clear_has_deprecated() {
+ _has_bits_[0] &= ~0x00000400u;
+}
+void FileOptions::clear_deprecated() {
+ deprecated_ = false;
+ clear_has_deprecated();
+}
+ bool FileOptions::deprecated() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.deprecated)
+ return deprecated_;
+}
+ void FileOptions::set_deprecated(bool value) {
+ set_has_deprecated();
+ deprecated_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.deprecated)
+}
+
+// optional bool cc_enable_arenas = 31 [default = false];
+bool FileOptions::has_cc_enable_arenas() const {
+ return (_has_bits_[0] & 0x00000800u) != 0;
+}
+void FileOptions::set_has_cc_enable_arenas() {
+ _has_bits_[0] |= 0x00000800u;
+}
+void FileOptions::clear_has_cc_enable_arenas() {
+ _has_bits_[0] &= ~0x00000800u;
+}
+void FileOptions::clear_cc_enable_arenas() {
+ cc_enable_arenas_ = false;
+ clear_has_cc_enable_arenas();
+}
+ bool FileOptions::cc_enable_arenas() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_enable_arenas)
+ return cc_enable_arenas_;
+}
+ void FileOptions::set_cc_enable_arenas(bool value) {
+ set_has_cc_enable_arenas();
+ cc_enable_arenas_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_enable_arenas)
+}
+
+// optional string objc_class_prefix = 36;
+bool FileOptions::has_objc_class_prefix() const {
+ return (_has_bits_[0] & 0x00001000u) != 0;
+}
+void FileOptions::set_has_objc_class_prefix() {
+ _has_bits_[0] |= 0x00001000u;
+}
+void FileOptions::clear_has_objc_class_prefix() {
+ _has_bits_[0] &= ~0x00001000u;
+}
+void FileOptions::clear_objc_class_prefix() {
+ objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_objc_class_prefix();
+}
+ const ::std::string& FileOptions::objc_class_prefix() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix)
+ return objc_class_prefix_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_objc_class_prefix(const ::std::string& value) {
+ set_has_objc_class_prefix();
+ objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix)
+}
+ void FileOptions::set_objc_class_prefix(const char* value) {
+ set_has_objc_class_prefix();
+ objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix)
+}
+ void FileOptions::set_objc_class_prefix(const char* value, size_t size) {
+ set_has_objc_class_prefix();
+ objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix)
+}
+ ::std::string* FileOptions::mutable_objc_class_prefix() {
+ set_has_objc_class_prefix();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix)
+ return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_objc_class_prefix() {
+ clear_has_objc_class_prefix();
+ return objc_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_objc_class_prefix(::std::string* objc_class_prefix) {
+ if (objc_class_prefix != NULL) {
+ set_has_objc_class_prefix();
+ } else {
+ clear_has_objc_class_prefix();
+ }
+ objc_class_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), objc_class_prefix);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix)
+}
+
+// optional string csharp_namespace = 37;
+bool FileOptions::has_csharp_namespace() const {
+ return (_has_bits_[0] & 0x00002000u) != 0;
+}
+void FileOptions::set_has_csharp_namespace() {
+ _has_bits_[0] |= 0x00002000u;
+}
+void FileOptions::clear_has_csharp_namespace() {
+ _has_bits_[0] &= ~0x00002000u;
+}
+void FileOptions::clear_csharp_namespace() {
+ csharp_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_csharp_namespace();
+}
+ const ::std::string& FileOptions::csharp_namespace() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_namespace)
+ return csharp_namespace_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_csharp_namespace(const ::std::string& value) {
+ set_has_csharp_namespace();
+ csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_namespace)
+}
+ void FileOptions::set_csharp_namespace(const char* value) {
+ set_has_csharp_namespace();
+ csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_namespace)
+}
+ void FileOptions::set_csharp_namespace(const char* value, size_t size) {
+ set_has_csharp_namespace();
+ csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_namespace)
+}
+ ::std::string* FileOptions::mutable_csharp_namespace() {
+ set_has_csharp_namespace();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_namespace)
+ return csharp_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_csharp_namespace() {
+ clear_has_csharp_namespace();
+ return csharp_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_csharp_namespace(::std::string* csharp_namespace) {
+ if (csharp_namespace != NULL) {
+ set_has_csharp_namespace();
+ } else {
+ clear_has_csharp_namespace();
+ }
+ csharp_namespace_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), csharp_namespace);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace)
+}
+
+// optional bool javanano_use_deprecated_package = 38;
+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();
+}
+void FileOptions::clear_uninterpreted_option() {
+ uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.uninterpreted_option)
+ return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* FileOptions::mutable_uninterpreted_option(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.uninterpreted_option)
+ return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_option() {
+ // @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option)
+ return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FileOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+FileOptions::mutable_uninterpreted_option() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option)
+ return &uninterpreted_option_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -5887,7 +9061,7 @@ const int MessageOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
MessageOptions::MessageOptions()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.MessageOptions)
}
@@ -5949,19 +9123,17 @@ MessageOptions* MessageOptions::New(::google::protobuf::Arena* arena) const {
void MessageOptions::Clear() {
_extensions_.Clear();
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
- &reinterpret_cast<MessageOptions*>(16)->f) - \
- reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<MessageOptions*>(16)->f)
-#define ZR_(first, last) do { \
- size_t f = OFFSET_OF_FIELD_(first); \
- size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \
- ::memset(&first, 0, n); \
- } while (0)
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
ZR_(message_set_wire_format_, map_entry_);
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
#undef ZR_
uninterpreted_option_.Clear();
@@ -6044,12 +9216,15 @@ bool MessageOptions::MergePartialFromCodedStream(
case 999: {
if (tag == 7994) {
parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_uninterpreted_option()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+ if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -6166,7 +9341,7 @@ void MessageOptions::SerializeWithCachedSizes(
int MessageOptions::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & 15) {
+ if (_has_bits_[0 / 32] & 15u) {
// optional bool message_set_wire_format = 1 [default = false];
if (has_message_set_wire_format()) {
total_size += 1 + 1;
@@ -6211,9 +9386,9 @@ int MessageOptions::ByteSize() const {
void MessageOptions::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const MessageOptions* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const MessageOptions*>(
- &from);
+ const MessageOptions* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const MessageOptions>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -6287,6 +9462,136 @@ void MessageOptions::InternalSwap(MessageOptions* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// MessageOptions
+
+// optional bool message_set_wire_format = 1 [default = false];
+bool MessageOptions::has_message_set_wire_format() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void MessageOptions::set_has_message_set_wire_format() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void MessageOptions::clear_has_message_set_wire_format() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void MessageOptions::clear_message_set_wire_format() {
+ message_set_wire_format_ = false;
+ clear_has_message_set_wire_format();
+}
+ bool MessageOptions::message_set_wire_format() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.message_set_wire_format)
+ return message_set_wire_format_;
+}
+ void MessageOptions::set_message_set_wire_format(bool value) {
+ set_has_message_set_wire_format();
+ message_set_wire_format_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.message_set_wire_format)
+}
+
+// optional bool no_standard_descriptor_accessor = 2 [default = false];
+bool MessageOptions::has_no_standard_descriptor_accessor() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void MessageOptions::set_has_no_standard_descriptor_accessor() {
+ _has_bits_[0] |= 0x00000002u;
+}
+void MessageOptions::clear_has_no_standard_descriptor_accessor() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+void MessageOptions::clear_no_standard_descriptor_accessor() {
+ no_standard_descriptor_accessor_ = false;
+ clear_has_no_standard_descriptor_accessor();
+}
+ bool MessageOptions::no_standard_descriptor_accessor() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.no_standard_descriptor_accessor)
+ return no_standard_descriptor_accessor_;
+}
+ void MessageOptions::set_no_standard_descriptor_accessor(bool value) {
+ set_has_no_standard_descriptor_accessor();
+ no_standard_descriptor_accessor_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.no_standard_descriptor_accessor)
+}
+
+// optional bool deprecated = 3 [default = false];
+bool MessageOptions::has_deprecated() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void MessageOptions::set_has_deprecated() {
+ _has_bits_[0] |= 0x00000004u;
+}
+void MessageOptions::clear_has_deprecated() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+void MessageOptions::clear_deprecated() {
+ deprecated_ = false;
+ clear_has_deprecated();
+}
+ bool MessageOptions::deprecated() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.deprecated)
+ return deprecated_;
+}
+ void MessageOptions::set_deprecated(bool value) {
+ set_has_deprecated();
+ deprecated_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.deprecated)
+}
+
+// optional bool map_entry = 7;
+bool MessageOptions::has_map_entry() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void MessageOptions::set_has_map_entry() {
+ _has_bits_[0] |= 0x00000008u;
+}
+void MessageOptions::clear_has_map_entry() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+void MessageOptions::clear_map_entry() {
+ map_entry_ = false;
+ clear_has_map_entry();
+}
+ bool MessageOptions::map_entry() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.map_entry)
+ return map_entry_;
+}
+ void MessageOptions::set_map_entry(bool value) {
+ set_has_map_entry();
+ map_entry_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.map_entry)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+int MessageOptions::uninterpreted_option_size() const {
+ return uninterpreted_option_.size();
+}
+void MessageOptions::clear_uninterpreted_option() {
+ uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.uninterpreted_option)
+ return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* MessageOptions::mutable_uninterpreted_option(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.MessageOptions.uninterpreted_option)
+ return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* MessageOptions::add_uninterpreted_option() {
+ // @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option)
+ return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MessageOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+MessageOptions::mutable_uninterpreted_option() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option)
+ return &uninterpreted_option_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -6313,9 +9618,33 @@ const FieldOptions_CType FieldOptions::CType_MIN;
const FieldOptions_CType FieldOptions::CType_MAX;
const int FieldOptions::CType_ARRAYSIZE;
#endif // _MSC_VER
+const ::google::protobuf::EnumDescriptor* FieldOptions_JSType_descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return FieldOptions_JSType_descriptor_;
+}
+bool FieldOptions_JSType_IsValid(int value) {
+ switch(value) {
+ case 0:
+ case 1:
+ case 2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+#ifndef _MSC_VER
+const FieldOptions_JSType FieldOptions::JS_NORMAL;
+const FieldOptions_JSType FieldOptions::JS_STRING;
+const FieldOptions_JSType FieldOptions::JS_NUMBER;
+const FieldOptions_JSType FieldOptions::JSType_MIN;
+const FieldOptions_JSType FieldOptions::JSType_MAX;
+const int FieldOptions::JSType_ARRAYSIZE;
+#endif // _MSC_VER
#ifndef _MSC_VER
const int FieldOptions::kCtypeFieldNumber;
const int FieldOptions::kPackedFieldNumber;
+const int FieldOptions::kJstypeFieldNumber;
const int FieldOptions::kLazyFieldNumber;
const int FieldOptions::kDeprecatedFieldNumber;
const int FieldOptions::kWeakFieldNumber;
@@ -6323,7 +9652,7 @@ const int FieldOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
FieldOptions::FieldOptions()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FieldOptions)
}
@@ -6343,6 +9672,7 @@ void FieldOptions::SharedCtor() {
_cached_size_ = 0;
ctype_ = 0;
packed_ = false;
+ jstype_ = 0;
lazy_ = false;
deprecated_ = false;
weak_ = false;
@@ -6386,21 +9716,20 @@ FieldOptions* FieldOptions::New(::google::protobuf::Arena* arena) const {
void FieldOptions::Clear() {
_extensions_.Clear();
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
- &reinterpret_cast<FieldOptions*>(16)->f) - \
- reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<FieldOptions*>(16)->f)
-#define ZR_(first, last) do { \
- size_t f = OFFSET_OF_FIELD_(first); \
- size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \
- ::memset(&first, 0, n); \
- } while (0)
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
- if (_has_bits_[0 / 32] & 31) {
- ZR_(ctype_, weak_);
+ if (_has_bits_[0 / 32] & 63u) {
+ ZR_(ctype_, jstype_);
+ ZR_(packed_, weak_);
}
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
#undef ZR_
uninterpreted_option_.Clear();
@@ -6480,6 +9809,26 @@ bool FieldOptions::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
+ if (input->ExpectTag(48)) goto parse_jstype;
+ break;
+ }
+
+ // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+ case 6: {
+ if (tag == 48) {
+ parse_jstype:
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ if (::google::protobuf::FieldOptions_JSType_IsValid(value)) {
+ set_jstype(static_cast< ::google::protobuf::FieldOptions_JSType >(value));
+ } else {
+ mutable_unknown_fields()->AddVarint(6, value);
+ }
+ } else {
+ goto handle_unusual;
+ }
if (input->ExpectTag(80)) goto parse_weak;
break;
}
@@ -6503,12 +9852,15 @@ bool FieldOptions::MergePartialFromCodedStream(
case 999: {
if (tag == 7994) {
parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_uninterpreted_option()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+ if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -6564,6 +9916,12 @@ void FieldOptions::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteBool(5, this->lazy(), output);
}
+ // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+ if (has_jstype()) {
+ ::google::protobuf::internal::WireFormatLite::WriteEnum(
+ 6, this->jstype(), output);
+ }
+
// optional bool weak = 10 [default = false];
if (has_weak()) {
::google::protobuf::internal::WireFormatLite::WriteBool(10, this->weak(), output);
@@ -6610,6 +9968,12 @@ void FieldOptions::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(5, this->lazy(), target);
}
+ // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+ if (has_jstype()) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+ 6, this->jstype(), target);
+ }
+
// optional bool weak = 10 [default = false];
if (has_weak()) {
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->weak(), target);
@@ -6637,7 +10001,7 @@ void FieldOptions::SerializeWithCachedSizes(
int FieldOptions::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & 31) {
+ if (_has_bits_[0 / 32] & 63u) {
// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
if (has_ctype()) {
total_size += 1 +
@@ -6649,6 +10013,12 @@ int FieldOptions::ByteSize() const {
total_size += 1 + 1;
}
+ // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+ if (has_jstype()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::EnumSize(this->jstype());
+ }
+
// optional bool lazy = 5 [default = false];
if (has_lazy()) {
total_size += 1 + 1;
@@ -6688,9 +10058,9 @@ int FieldOptions::ByteSize() const {
void FieldOptions::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const FieldOptions* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const FieldOptions*>(
- &from);
+ const FieldOptions* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const FieldOptions>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -6708,6 +10078,9 @@ void FieldOptions::MergeFrom(const FieldOptions& from) {
if (from.has_packed()) {
set_packed(from.packed());
}
+ if (from.has_jstype()) {
+ set_jstype(from.jstype());
+ }
if (from.has_lazy()) {
set_lazy(from.lazy());
}
@@ -6750,6 +10123,7 @@ void FieldOptions::Swap(FieldOptions* other) {
void FieldOptions::InternalSwap(FieldOptions* other) {
std::swap(ctype_, other->ctype_);
std::swap(packed_, other->packed_);
+ std::swap(jstype_, other->jstype_);
std::swap(lazy_, other->lazy_);
std::swap(deprecated_, other->deprecated_);
std::swap(weak_, other->weak_);
@@ -6768,6 +10142,186 @@ void FieldOptions::InternalSwap(FieldOptions* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FieldOptions
+
+// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
+bool FieldOptions::has_ctype() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void FieldOptions::set_has_ctype() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void FieldOptions::clear_has_ctype() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void FieldOptions::clear_ctype() {
+ ctype_ = 0;
+ clear_has_ctype();
+}
+ ::google::protobuf::FieldOptions_CType FieldOptions::ctype() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.ctype)
+ return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_);
+}
+ void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) {
+ assert(::google::protobuf::FieldOptions_CType_IsValid(value));
+ set_has_ctype();
+ ctype_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.ctype)
+}
+
+// optional bool packed = 2;
+bool FieldOptions::has_packed() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void FieldOptions::set_has_packed() {
+ _has_bits_[0] |= 0x00000002u;
+}
+void FieldOptions::clear_has_packed() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+void FieldOptions::clear_packed() {
+ packed_ = false;
+ clear_has_packed();
+}
+ bool FieldOptions::packed() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.packed)
+ return packed_;
+}
+ void FieldOptions::set_packed(bool value) {
+ set_has_packed();
+ packed_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed)
+}
+
+// optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+bool FieldOptions::has_jstype() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void FieldOptions::set_has_jstype() {
+ _has_bits_[0] |= 0x00000004u;
+}
+void FieldOptions::clear_has_jstype() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+void FieldOptions::clear_jstype() {
+ jstype_ = 0;
+ clear_has_jstype();
+}
+ ::google::protobuf::FieldOptions_JSType FieldOptions::jstype() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.jstype)
+ return static_cast< ::google::protobuf::FieldOptions_JSType >(jstype_);
+}
+ void FieldOptions::set_jstype(::google::protobuf::FieldOptions_JSType value) {
+ assert(::google::protobuf::FieldOptions_JSType_IsValid(value));
+ set_has_jstype();
+ jstype_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.jstype)
+}
+
+// optional bool lazy = 5 [default = false];
+bool FieldOptions::has_lazy() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void FieldOptions::set_has_lazy() {
+ _has_bits_[0] |= 0x00000008u;
+}
+void FieldOptions::clear_has_lazy() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+void FieldOptions::clear_lazy() {
+ lazy_ = false;
+ clear_has_lazy();
+}
+ bool FieldOptions::lazy() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.lazy)
+ return lazy_;
+}
+ void FieldOptions::set_lazy(bool value) {
+ set_has_lazy();
+ lazy_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.lazy)
+}
+
+// optional bool deprecated = 3 [default = false];
+bool FieldOptions::has_deprecated() const {
+ return (_has_bits_[0] & 0x00000010u) != 0;
+}
+void FieldOptions::set_has_deprecated() {
+ _has_bits_[0] |= 0x00000010u;
+}
+void FieldOptions::clear_has_deprecated() {
+ _has_bits_[0] &= ~0x00000010u;
+}
+void FieldOptions::clear_deprecated() {
+ deprecated_ = false;
+ clear_has_deprecated();
+}
+ bool FieldOptions::deprecated() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.deprecated)
+ return deprecated_;
+}
+ void FieldOptions::set_deprecated(bool value) {
+ set_has_deprecated();
+ deprecated_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.deprecated)
+}
+
+// optional bool weak = 10 [default = false];
+bool FieldOptions::has_weak() const {
+ return (_has_bits_[0] & 0x00000020u) != 0;
+}
+void FieldOptions::set_has_weak() {
+ _has_bits_[0] |= 0x00000020u;
+}
+void FieldOptions::clear_has_weak() {
+ _has_bits_[0] &= ~0x00000020u;
+}
+void FieldOptions::clear_weak() {
+ weak_ = false;
+ clear_has_weak();
+}
+ bool FieldOptions::weak() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.weak)
+ return weak_;
+}
+ void FieldOptions::set_weak(bool value) {
+ set_has_weak();
+ weak_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.weak)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+int FieldOptions::uninterpreted_option_size() const {
+ return uninterpreted_option_.size();
+}
+void FieldOptions::clear_uninterpreted_option() {
+ uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.uninterpreted_option)
+ return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* FieldOptions::mutable_uninterpreted_option(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.uninterpreted_option)
+ return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_option() {
+ // @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option)
+ return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FieldOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+FieldOptions::mutable_uninterpreted_option() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option)
+ return &uninterpreted_option_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -6778,7 +10332,7 @@ const int EnumOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
EnumOptions::EnumOptions()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.EnumOptions)
}
@@ -6838,19 +10392,17 @@ EnumOptions* EnumOptions::New(::google::protobuf::Arena* arena) const {
void EnumOptions::Clear() {
_extensions_.Clear();
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
- &reinterpret_cast<EnumOptions*>(16)->f) - \
- reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<EnumOptions*>(16)->f)
-#define ZR_(first, last) do { \
- size_t f = OFFSET_OF_FIELD_(first); \
- size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \
- ::memset(&first, 0, n); \
- } while (0)
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
ZR_(allow_alias_, deprecated_);
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
#undef ZR_
uninterpreted_option_.Clear();
@@ -6903,12 +10455,15 @@ bool EnumOptions::MergePartialFromCodedStream(
case 999: {
if (tag == 7994) {
parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_uninterpreted_option()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+ if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -7005,7 +10560,7 @@ void EnumOptions::SerializeWithCachedSizes(
int EnumOptions::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & 3) {
+ if (_has_bits_[0 / 32] & 3u) {
// optional bool allow_alias = 2;
if (has_allow_alias()) {
total_size += 1 + 1;
@@ -7040,9 +10595,9 @@ int EnumOptions::ByteSize() const {
void EnumOptions::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const EnumOptions* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const EnumOptions*>(
- &from);
+ const EnumOptions* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const EnumOptions>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -7108,6 +10663,88 @@ void EnumOptions::InternalSwap(EnumOptions* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumOptions
+
+// optional bool allow_alias = 2;
+bool EnumOptions::has_allow_alias() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void EnumOptions::set_has_allow_alias() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void EnumOptions::clear_has_allow_alias() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void EnumOptions::clear_allow_alias() {
+ allow_alias_ = false;
+ clear_has_allow_alias();
+}
+ bool EnumOptions::allow_alias() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.allow_alias)
+ return allow_alias_;
+}
+ void EnumOptions::set_allow_alias(bool value) {
+ set_has_allow_alias();
+ allow_alias_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.allow_alias)
+}
+
+// optional bool deprecated = 3 [default = false];
+bool EnumOptions::has_deprecated() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void EnumOptions::set_has_deprecated() {
+ _has_bits_[0] |= 0x00000002u;
+}
+void EnumOptions::clear_has_deprecated() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+void EnumOptions::clear_deprecated() {
+ deprecated_ = false;
+ clear_has_deprecated();
+}
+ bool EnumOptions::deprecated() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.deprecated)
+ return deprecated_;
+}
+ void EnumOptions::set_deprecated(bool value) {
+ set_has_deprecated();
+ deprecated_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+int EnumOptions::uninterpreted_option_size() const {
+ return uninterpreted_option_.size();
+}
+void EnumOptions::clear_uninterpreted_option() {
+ uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.uninterpreted_option)
+ return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* EnumOptions::mutable_uninterpreted_option(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumOptions.uninterpreted_option)
+ return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_option() {
+ // @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option)
+ return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+EnumOptions::mutable_uninterpreted_option() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option)
+ return &uninterpreted_option_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -7117,7 +10754,7 @@ const int EnumValueOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
EnumValueOptions::EnumValueOptions()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.EnumValueOptions)
}
@@ -7212,12 +10849,15 @@ bool EnumValueOptions::MergePartialFromCodedStream(
case 999: {
if (tag == 7994) {
parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_uninterpreted_option()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+ if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -7332,9 +10972,9 @@ int EnumValueOptions::ByteSize() const {
void EnumValueOptions::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const EnumValueOptions* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const EnumValueOptions*>(
- &from);
+ const EnumValueOptions* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const EnumValueOptions>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -7396,6 +11036,64 @@ void EnumValueOptions::InternalSwap(EnumValueOptions* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumValueOptions
+
+// optional bool deprecated = 1 [default = false];
+bool EnumValueOptions::has_deprecated() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void EnumValueOptions::set_has_deprecated() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void EnumValueOptions::clear_has_deprecated() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void EnumValueOptions::clear_deprecated() {
+ deprecated_ = false;
+ clear_has_deprecated();
+}
+ bool EnumValueOptions::deprecated() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.deprecated)
+ return deprecated_;
+}
+ void EnumValueOptions::set_deprecated(bool value) {
+ set_has_deprecated();
+ deprecated_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumValueOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+int EnumValueOptions::uninterpreted_option_size() const {
+ return uninterpreted_option_.size();
+}
+void EnumValueOptions::clear_uninterpreted_option() {
+ uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.uninterpreted_option)
+ return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* EnumValueOptions::mutable_uninterpreted_option(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueOptions.uninterpreted_option)
+ return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() {
+ // @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option)
+ return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumValueOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+EnumValueOptions::mutable_uninterpreted_option() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option)
+ return &uninterpreted_option_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -7405,7 +11103,7 @@ const int ServiceOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
ServiceOptions::ServiceOptions()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.ServiceOptions)
}
@@ -7500,12 +11198,15 @@ bool ServiceOptions::MergePartialFromCodedStream(
case 999: {
if (tag == 7994) {
parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_uninterpreted_option()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+ if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -7620,9 +11321,9 @@ int ServiceOptions::ByteSize() const {
void ServiceOptions::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const ServiceOptions* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const ServiceOptions*>(
- &from);
+ const ServiceOptions* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const ServiceOptions>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -7684,6 +11385,64 @@ void ServiceOptions::InternalSwap(ServiceOptions* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// ServiceOptions
+
+// optional bool deprecated = 33 [default = false];
+bool ServiceOptions::has_deprecated() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void ServiceOptions::set_has_deprecated() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void ServiceOptions::clear_has_deprecated() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void ServiceOptions::clear_deprecated() {
+ deprecated_ = false;
+ clear_has_deprecated();
+}
+ bool ServiceOptions::deprecated() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.deprecated)
+ return deprecated_;
+}
+ void ServiceOptions::set_deprecated(bool value) {
+ set_has_deprecated();
+ deprecated_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.ServiceOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+int ServiceOptions::uninterpreted_option_size() const {
+ return uninterpreted_option_.size();
+}
+void ServiceOptions::clear_uninterpreted_option() {
+ uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.uninterpreted_option)
+ return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* ServiceOptions::mutable_uninterpreted_option(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceOptions.uninterpreted_option)
+ return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterpreted_option() {
+ // @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option)
+ return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ServiceOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ServiceOptions::mutable_uninterpreted_option() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option)
+ return &uninterpreted_option_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -7693,7 +11452,7 @@ const int MethodOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
MethodOptions::MethodOptions()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.MethodOptions)
}
@@ -7788,12 +11547,15 @@ bool MethodOptions::MergePartialFromCodedStream(
case 999: {
if (tag == 7994) {
parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_uninterpreted_option()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+ if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -7908,9 +11670,9 @@ int MethodOptions::ByteSize() const {
void MethodOptions::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const MethodOptions* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const MethodOptions*>(
- &from);
+ const MethodOptions* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const MethodOptions>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -7972,6 +11734,64 @@ void MethodOptions::InternalSwap(MethodOptions* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// MethodOptions
+
+// optional bool deprecated = 33 [default = false];
+bool MethodOptions::has_deprecated() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void MethodOptions::set_has_deprecated() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void MethodOptions::clear_has_deprecated() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void MethodOptions::clear_deprecated() {
+ deprecated_ = false;
+ clear_has_deprecated();
+}
+ bool MethodOptions::deprecated() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.deprecated)
+ return deprecated_;
+}
+ void MethodOptions::set_deprecated(bool value) {
+ set_has_deprecated();
+ deprecated_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.MethodOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+int MethodOptions::uninterpreted_option_size() const {
+ return uninterpreted_option_.size();
+}
+void MethodOptions::clear_uninterpreted_option() {
+ uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.uninterpreted_option)
+ return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* MethodOptions::mutable_uninterpreted_option(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.MethodOptions.uninterpreted_option)
+ return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted_option() {
+ // @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option)
+ return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MethodOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+MethodOptions::mutable_uninterpreted_option() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option)
+ return &uninterpreted_option_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -7981,7 +11801,7 @@ const int UninterpretedOption_NamePart::kIsExtensionFieldNumber;
#endif // !_MSC_VER
UninterpretedOption_NamePart::UninterpretedOption_NamePart()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption.NamePart)
}
@@ -8042,7 +11862,7 @@ UninterpretedOption_NamePart* UninterpretedOption_NamePart::New(::google::protob
}
void UninterpretedOption_NamePart::Clear() {
- if (_has_bits_[0 / 32] & 3) {
+ if (_has_bits_[0 / 32] & 3u) {
if (has_name_part()) {
name_part_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -8214,9 +12034,9 @@ int UninterpretedOption_NamePart::ByteSize() const {
void UninterpretedOption_NamePart::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const UninterpretedOption_NamePart* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const UninterpretedOption_NamePart*>(
- &from);
+ const UninterpretedOption_NamePart* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const UninterpretedOption_NamePart>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -8292,7 +12112,7 @@ const int UninterpretedOption::kAggregateValueFieldNumber;
#endif // !_MSC_VER
UninterpretedOption::UninterpretedOption()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption)
}
@@ -8359,17 +12179,15 @@ UninterpretedOption* UninterpretedOption::New(::google::protobuf::Arena* arena)
}
void UninterpretedOption::Clear() {
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
- &reinterpret_cast<UninterpretedOption*>(16)->f) - \
- reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<UninterpretedOption*>(16)->f)
-#define ZR_(first, last) do { \
- size_t f = OFFSET_OF_FIELD_(first); \
- size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \
- ::memset(&first, 0, n); \
- } while (0)
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
- if (_has_bits_[0 / 32] & 126) {
+ if (_has_bits_[0 / 32] & 126u) {
ZR_(positive_int_value_, double_value_);
if (has_identifier_value()) {
identifier_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@@ -8382,7 +12200,7 @@ void UninterpretedOption::Clear() {
}
}
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
#undef ZR_
name_.Clear();
@@ -8405,13 +12223,15 @@ bool UninterpretedOption::MergePartialFromCodedStream(
// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
case 2: {
if (tag == 18) {
- parse_name:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_name:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_name()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(18)) goto parse_name;
+ if (input->ExpectTag(18)) goto parse_loop_name;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectTag(26)) goto parse_identifier_value;
break;
}
@@ -8652,7 +12472,7 @@ void UninterpretedOption::SerializeWithCachedSizes(
int UninterpretedOption::ByteSize() const {
int total_size = 0;
- if (_has_bits_[1 / 32] & 126) {
+ if (_has_bits_[1 / 32] & 126u) {
// optional string identifier_value = 3;
if (has_identifier_value()) {
total_size += 1 +
@@ -8715,9 +12535,9 @@ int UninterpretedOption::ByteSize() const {
void UninterpretedOption::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const UninterpretedOption* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const UninterpretedOption*>(
- &from);
+ const UninterpretedOption* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const UninterpretedOption>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -8799,6 +12619,352 @@ void UninterpretedOption::InternalSwap(UninterpretedOption* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// UninterpretedOption_NamePart
+
+// required string name_part = 1;
+bool UninterpretedOption_NamePart::has_name_part() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void UninterpretedOption_NamePart::set_has_name_part() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void UninterpretedOption_NamePart::clear_has_name_part() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void UninterpretedOption_NamePart::clear_name_part() {
+ name_part_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name_part();
+}
+ const ::std::string& UninterpretedOption_NamePart::name_part() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.name_part)
+ return name_part_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption_NamePart::set_name_part(const ::std::string& value) {
+ set_has_name_part();
+ name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+ void UninterpretedOption_NamePart::set_name_part(const char* value) {
+ set_has_name_part();
+ name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+ void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) {
+ set_has_name_part();
+ name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+ ::std::string* UninterpretedOption_NamePart::mutable_name_part() {
+ set_has_name_part();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.NamePart.name_part)
+ return name_part_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* UninterpretedOption_NamePart::release_name_part() {
+ clear_has_name_part();
+ return name_part_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption_NamePart::set_allocated_name_part(::std::string* name_part) {
+ if (name_part != NULL) {
+ set_has_name_part();
+ } else {
+ clear_has_name_part();
+ }
+ name_part_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name_part);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+
+// required bool is_extension = 2;
+bool UninterpretedOption_NamePart::has_is_extension() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void UninterpretedOption_NamePart::set_has_is_extension() {
+ _has_bits_[0] |= 0x00000002u;
+}
+void UninterpretedOption_NamePart::clear_has_is_extension() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+void UninterpretedOption_NamePart::clear_is_extension() {
+ is_extension_ = false;
+ clear_has_is_extension();
+}
+ bool UninterpretedOption_NamePart::is_extension() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.is_extension)
+ return is_extension_;
+}
+ void UninterpretedOption_NamePart::set_is_extension(bool value) {
+ set_has_is_extension();
+ is_extension_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.is_extension)
+}
+
+// -------------------------------------------------------------------
+
+// UninterpretedOption
+
+// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
+int UninterpretedOption::name_size() const {
+ return name_.size();
+}
+void UninterpretedOption::clear_name() {
+ name_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.name)
+ return name_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::mutable_name(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.name)
+ return name_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::add_name() {
+ // @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name)
+ return name_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+UninterpretedOption::name() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name)
+ return name_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
+UninterpretedOption::mutable_name() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name)
+ return &name_;
+}
+
+// optional string identifier_value = 3;
+bool UninterpretedOption::has_identifier_value() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void UninterpretedOption::set_has_identifier_value() {
+ _has_bits_[0] |= 0x00000002u;
+}
+void UninterpretedOption::clear_has_identifier_value() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+void UninterpretedOption::clear_identifier_value() {
+ identifier_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_identifier_value();
+}
+ const ::std::string& UninterpretedOption::identifier_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.identifier_value)
+ return identifier_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_identifier_value(const ::std::string& value) {
+ set_has_identifier_value();
+ identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.identifier_value)
+}
+ void UninterpretedOption::set_identifier_value(const char* value) {
+ set_has_identifier_value();
+ identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.identifier_value)
+}
+ void UninterpretedOption::set_identifier_value(const char* value, size_t size) {
+ set_has_identifier_value();
+ identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.identifier_value)
+}
+ ::std::string* UninterpretedOption::mutable_identifier_value() {
+ set_has_identifier_value();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.identifier_value)
+ return identifier_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* UninterpretedOption::release_identifier_value() {
+ clear_has_identifier_value();
+ return identifier_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_allocated_identifier_value(::std::string* identifier_value) {
+ if (identifier_value != NULL) {
+ set_has_identifier_value();
+ } else {
+ clear_has_identifier_value();
+ }
+ identifier_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), identifier_value);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.identifier_value)
+}
+
+// optional uint64 positive_int_value = 4;
+bool UninterpretedOption::has_positive_int_value() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void UninterpretedOption::set_has_positive_int_value() {
+ _has_bits_[0] |= 0x00000004u;
+}
+void UninterpretedOption::clear_has_positive_int_value() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+void UninterpretedOption::clear_positive_int_value() {
+ positive_int_value_ = GOOGLE_ULONGLONG(0);
+ clear_has_positive_int_value();
+}
+ ::google::protobuf::uint64 UninterpretedOption::positive_int_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.positive_int_value)
+ return positive_int_value_;
+}
+ void UninterpretedOption::set_positive_int_value(::google::protobuf::uint64 value) {
+ set_has_positive_int_value();
+ positive_int_value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.positive_int_value)
+}
+
+// optional int64 negative_int_value = 5;
+bool UninterpretedOption::has_negative_int_value() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void UninterpretedOption::set_has_negative_int_value() {
+ _has_bits_[0] |= 0x00000008u;
+}
+void UninterpretedOption::clear_has_negative_int_value() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+void UninterpretedOption::clear_negative_int_value() {
+ negative_int_value_ = GOOGLE_LONGLONG(0);
+ clear_has_negative_int_value();
+}
+ ::google::protobuf::int64 UninterpretedOption::negative_int_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.negative_int_value)
+ return negative_int_value_;
+}
+ void UninterpretedOption::set_negative_int_value(::google::protobuf::int64 value) {
+ set_has_negative_int_value();
+ negative_int_value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.negative_int_value)
+}
+
+// optional double double_value = 6;
+bool UninterpretedOption::has_double_value() const {
+ return (_has_bits_[0] & 0x00000010u) != 0;
+}
+void UninterpretedOption::set_has_double_value() {
+ _has_bits_[0] |= 0x00000010u;
+}
+void UninterpretedOption::clear_has_double_value() {
+ _has_bits_[0] &= ~0x00000010u;
+}
+void UninterpretedOption::clear_double_value() {
+ double_value_ = 0;
+ clear_has_double_value();
+}
+ double UninterpretedOption::double_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.double_value)
+ return double_value_;
+}
+ void UninterpretedOption::set_double_value(double value) {
+ set_has_double_value();
+ double_value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.double_value)
+}
+
+// optional bytes string_value = 7;
+bool UninterpretedOption::has_string_value() const {
+ return (_has_bits_[0] & 0x00000020u) != 0;
+}
+void UninterpretedOption::set_has_string_value() {
+ _has_bits_[0] |= 0x00000020u;
+}
+void UninterpretedOption::clear_has_string_value() {
+ _has_bits_[0] &= ~0x00000020u;
+}
+void UninterpretedOption::clear_string_value() {
+ string_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_string_value();
+}
+ const ::std::string& UninterpretedOption::string_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.string_value)
+ return string_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_string_value(const ::std::string& value) {
+ set_has_string_value();
+ string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.string_value)
+}
+ void UninterpretedOption::set_string_value(const char* value) {
+ set_has_string_value();
+ string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.string_value)
+}
+ void UninterpretedOption::set_string_value(const void* value, size_t size) {
+ set_has_string_value();
+ string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.string_value)
+}
+ ::std::string* UninterpretedOption::mutable_string_value() {
+ set_has_string_value();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.string_value)
+ return string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* UninterpretedOption::release_string_value() {
+ clear_has_string_value();
+ return string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_allocated_string_value(::std::string* string_value) {
+ if (string_value != NULL) {
+ set_has_string_value();
+ } else {
+ clear_has_string_value();
+ }
+ string_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), string_value);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.string_value)
+}
+
+// optional string aggregate_value = 8;
+bool UninterpretedOption::has_aggregate_value() const {
+ return (_has_bits_[0] & 0x00000040u) != 0;
+}
+void UninterpretedOption::set_has_aggregate_value() {
+ _has_bits_[0] |= 0x00000040u;
+}
+void UninterpretedOption::clear_has_aggregate_value() {
+ _has_bits_[0] &= ~0x00000040u;
+}
+void UninterpretedOption::clear_aggregate_value() {
+ aggregate_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_aggregate_value();
+}
+ const ::std::string& UninterpretedOption::aggregate_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.aggregate_value)
+ return aggregate_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_aggregate_value(const ::std::string& value) {
+ set_has_aggregate_value();
+ aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.aggregate_value)
+}
+ void UninterpretedOption::set_aggregate_value(const char* value) {
+ set_has_aggregate_value();
+ aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.aggregate_value)
+}
+ void UninterpretedOption::set_aggregate_value(const char* value, size_t size) {
+ set_has_aggregate_value();
+ aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.aggregate_value)
+}
+ ::std::string* UninterpretedOption::mutable_aggregate_value() {
+ set_has_aggregate_value();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.aggregate_value)
+ return aggregate_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* UninterpretedOption::release_aggregate_value() {
+ clear_has_aggregate_value();
+ return aggregate_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_allocated_aggregate_value(::std::string* aggregate_value) {
+ if (aggregate_value != NULL) {
+ set_has_aggregate_value();
+ } else {
+ clear_has_aggregate_value();
+ }
+ aggregate_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), aggregate_value);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -8807,10 +12973,11 @@ const int SourceCodeInfo_Location::kPathFieldNumber;
const int SourceCodeInfo_Location::kSpanFieldNumber;
const int SourceCodeInfo_Location::kLeadingCommentsFieldNumber;
const int SourceCodeInfo_Location::kTrailingCommentsFieldNumber;
+const int SourceCodeInfo_Location::kLeadingDetachedCommentsFieldNumber;
#endif // !_MSC_VER
SourceCodeInfo_Location::SourceCodeInfo_Location()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo.Location)
}
@@ -8872,7 +13039,7 @@ SourceCodeInfo_Location* SourceCodeInfo_Location::New(::google::protobuf::Arena*
}
void SourceCodeInfo_Location::Clear() {
- if (_has_bits_[0 / 32] & 12) {
+ if (_has_bits_[0 / 32] & 12u) {
if (has_leading_comments()) {
leading_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -8882,6 +13049,7 @@ void SourceCodeInfo_Location::Clear() {
}
path_.Clear();
span_.Clear();
+ leading_detached_comments_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
if (_internal_metadata_.have_unknown_fields()) {
mutable_unknown_fields()->Clear();
@@ -8963,6 +13131,25 @@ bool SourceCodeInfo_Location::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
+ if (input->ExpectTag(50)) goto parse_leading_detached_comments;
+ break;
+ }
+
+ // repeated string leading_detached_comments = 6;
+ case 6: {
+ if (tag == 50) {
+ parse_leading_detached_comments:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->add_leading_detached_comments()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->leading_detached_comments(this->leading_detached_comments_size() - 1).data(),
+ this->leading_detached_comments(this->leading_detached_comments_size() - 1).length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(50)) goto parse_leading_detached_comments;
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -9032,6 +13219,16 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
4, this->trailing_comments(), output);
}
+ // repeated string leading_detached_comments = 6;
+ for (int i = 0; i < this->leading_detached_comments_size(); i++) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->leading_detached_comments(i).data(), this->leading_detached_comments(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
+ ::google::protobuf::internal::WireFormatLite::WriteString(
+ 6, this->leading_detached_comments(i), output);
+ }
+
if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
@@ -9092,6 +13289,16 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
4, this->trailing_comments(), target);
}
+ // repeated string leading_detached_comments = 6;
+ for (int i = 0; i < this->leading_detached_comments_size(); i++) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->leading_detached_comments(i).data(), this->leading_detached_comments(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteStringToArray(6, this->leading_detached_comments(i), target);
+ }
+
if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -9103,7 +13310,7 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
int SourceCodeInfo_Location::ByteSize() const {
int total_size = 0;
- if (_has_bits_[2 / 32] & 12) {
+ if (_has_bits_[2 / 32] & 12u) {
// optional string leading_comments = 3;
if (has_leading_comments()) {
total_size += 1 +
@@ -9153,6 +13360,13 @@ int SourceCodeInfo_Location::ByteSize() const {
total_size += data_size;
}
+ // repeated string leading_detached_comments = 6;
+ total_size += 1 * this->leading_detached_comments_size();
+ for (int i = 0; i < this->leading_detached_comments_size(); i++) {
+ total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->leading_detached_comments(i));
+ }
+
if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
@@ -9166,9 +13380,9 @@ int SourceCodeInfo_Location::ByteSize() const {
void SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const SourceCodeInfo_Location* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const SourceCodeInfo_Location*>(
- &from);
+ const SourceCodeInfo_Location* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const SourceCodeInfo_Location>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -9180,6 +13394,7 @@ void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
path_.MergeFrom(from.path_);
span_.MergeFrom(from.span_);
+ leading_detached_comments_.MergeFrom(from.leading_detached_comments_);
if (from._has_bits_[2 / 32] & (0xffu << (2 % 32))) {
if (from.has_leading_comments()) {
set_has_leading_comments();
@@ -9221,6 +13436,7 @@ void SourceCodeInfo_Location::InternalSwap(SourceCodeInfo_Location* other) {
span_.UnsafeArenaSwap(&other->span_);
leading_comments_.Swap(&other->leading_comments_);
trailing_comments_.Swap(&other->trailing_comments_);
+ leading_detached_comments_.UnsafeArenaSwap(&other->leading_detached_comments_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_internal_metadata_.Swap(&other->_internal_metadata_);
std::swap(_cached_size_, other->_cached_size_);
@@ -9242,7 +13458,7 @@ const int SourceCodeInfo::kLocationFieldNumber;
#endif // !_MSC_VER
SourceCodeInfo::SourceCodeInfo()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo)
}
@@ -9319,13 +13535,15 @@ bool SourceCodeInfo::MergePartialFromCodedStream(
// repeated .google.protobuf.SourceCodeInfo.Location location = 1;
case 1: {
if (tag == 10) {
- parse_location:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_location:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_location()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(10)) goto parse_location;
+ if (input->ExpectTag(10)) goto parse_loop_location;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -9410,9 +13628,9 @@ int SourceCodeInfo::ByteSize() const {
void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const SourceCodeInfo* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const SourceCodeInfo*>(
- &from);
+ const SourceCodeInfo* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const SourceCodeInfo>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -9464,6 +13682,264 @@ void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// SourceCodeInfo_Location
+
+// repeated int32 path = 1 [packed = true];
+int SourceCodeInfo_Location::path_size() const {
+ return path_.size();
+}
+void SourceCodeInfo_Location::clear_path() {
+ path_.Clear();
+}
+ ::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.path)
+ return path_.Get(index);
+}
+ void SourceCodeInfo_Location::set_path(int index, ::google::protobuf::int32 value) {
+ path_.Set(index, value);
+ // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.path)
+}
+ void SourceCodeInfo_Location::add_path(::google::protobuf::int32 value) {
+ path_.Add(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.path)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+SourceCodeInfo_Location::path() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.path)
+ return path_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+SourceCodeInfo_Location::mutable_path() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.path)
+ return &path_;
+}
+
+// repeated int32 span = 2 [packed = true];
+int SourceCodeInfo_Location::span_size() const {
+ return span_.size();
+}
+void SourceCodeInfo_Location::clear_span() {
+ span_.Clear();
+}
+ ::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.span)
+ return span_.Get(index);
+}
+ void SourceCodeInfo_Location::set_span(int index, ::google::protobuf::int32 value) {
+ span_.Set(index, value);
+ // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.span)
+}
+ void SourceCodeInfo_Location::add_span(::google::protobuf::int32 value) {
+ span_.Add(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.span)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+SourceCodeInfo_Location::span() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.span)
+ return span_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+SourceCodeInfo_Location::mutable_span() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.span)
+ return &span_;
+}
+
+// optional string leading_comments = 3;
+bool SourceCodeInfo_Location::has_leading_comments() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+void SourceCodeInfo_Location::set_has_leading_comments() {
+ _has_bits_[0] |= 0x00000004u;
+}
+void SourceCodeInfo_Location::clear_has_leading_comments() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+void SourceCodeInfo_Location::clear_leading_comments() {
+ leading_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_leading_comments();
+}
+ const ::std::string& SourceCodeInfo_Location::leading_comments() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_comments)
+ return leading_comments_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceCodeInfo_Location::set_leading_comments(const ::std::string& value) {
+ set_has_leading_comments();
+ leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+ void SourceCodeInfo_Location::set_leading_comments(const char* value) {
+ set_has_leading_comments();
+ leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+ void SourceCodeInfo_Location::set_leading_comments(const char* value, size_t size) {
+ set_has_leading_comments();
+ leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+ ::std::string* SourceCodeInfo_Location::mutable_leading_comments() {
+ set_has_leading_comments();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_comments)
+ return leading_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* SourceCodeInfo_Location::release_leading_comments() {
+ clear_has_leading_comments();
+ return leading_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceCodeInfo_Location::set_allocated_leading_comments(::std::string* leading_comments) {
+ if (leading_comments != NULL) {
+ set_has_leading_comments();
+ } else {
+ clear_has_leading_comments();
+ }
+ leading_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), leading_comments);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+
+// optional string trailing_comments = 4;
+bool SourceCodeInfo_Location::has_trailing_comments() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void SourceCodeInfo_Location::set_has_trailing_comments() {
+ _has_bits_[0] |= 0x00000008u;
+}
+void SourceCodeInfo_Location::clear_has_trailing_comments() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+void SourceCodeInfo_Location::clear_trailing_comments() {
+ trailing_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_trailing_comments();
+}
+ const ::std::string& SourceCodeInfo_Location::trailing_comments() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+ return trailing_comments_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceCodeInfo_Location::set_trailing_comments(const ::std::string& value) {
+ set_has_trailing_comments();
+ trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+ void SourceCodeInfo_Location::set_trailing_comments(const char* value) {
+ set_has_trailing_comments();
+ trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+ void SourceCodeInfo_Location::set_trailing_comments(const char* value, size_t size) {
+ set_has_trailing_comments();
+ trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+ ::std::string* SourceCodeInfo_Location::mutable_trailing_comments() {
+ set_has_trailing_comments();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+ return trailing_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* SourceCodeInfo_Location::release_trailing_comments() {
+ clear_has_trailing_comments();
+ return trailing_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::string* trailing_comments) {
+ if (trailing_comments != NULL) {
+ set_has_trailing_comments();
+ } else {
+ clear_has_trailing_comments();
+ }
+ trailing_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), trailing_comments);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+
+// repeated string leading_detached_comments = 6;
+int SourceCodeInfo_Location::leading_detached_comments_size() const {
+ return leading_detached_comments_.size();
+}
+void SourceCodeInfo_Location::clear_leading_detached_comments() {
+ leading_detached_comments_.Clear();
+}
+ const ::std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ return leading_detached_comments_.Get(index);
+}
+ ::std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ return leading_detached_comments_.Mutable(index);
+}
+ void SourceCodeInfo_Location::set_leading_detached_comments(int index, const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ leading_detached_comments_.Mutable(index)->assign(value);
+}
+ void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) {
+ leading_detached_comments_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, size_t size) {
+ leading_detached_comments_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ ::std::string* SourceCodeInfo_Location::add_leading_detached_comments() {
+ return leading_detached_comments_.Add();
+}
+ void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) {
+ leading_detached_comments_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) {
+ leading_detached_comments_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, size_t size) {
+ leading_detached_comments_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+SourceCodeInfo_Location::leading_detached_comments() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ return leading_detached_comments_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+SourceCodeInfo_Location::mutable_leading_detached_comments() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ return &leading_detached_comments_;
+}
+
+// -------------------------------------------------------------------
+
+// SourceCodeInfo
+
+// repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+int SourceCodeInfo::location_size() const {
+ return location_.size();
+}
+void SourceCodeInfo::clear_location() {
+ location_.Clear();
+}
+ const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.location)
+ return location_.Get(index);
+}
+ ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.location)
+ return location_.Mutable(index);
+}
+ ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() {
+ // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location)
+ return location_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+SourceCodeInfo::location() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location)
+ return location_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
+SourceCodeInfo::mutable_location() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location)
+ return &location_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index cda25982..2aa076ae 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -42,6 +42,7 @@ class FileDescriptorSet;
class FileDescriptorProto;
class DescriptorProto;
class DescriptorProto_ExtensionRange;
+class DescriptorProto_ReservedRange;
class FieldDescriptorProto;
class OneofDescriptorProto;
class EnumDescriptorProto;
@@ -155,6 +156,26 @@ inline bool FieldOptions_CType_Parse(
return ::google::protobuf::internal::ParseNamedEnum<FieldOptions_CType>(
FieldOptions_CType_descriptor(), name, value);
}
+enum FieldOptions_JSType {
+ FieldOptions_JSType_JS_NORMAL = 0,
+ FieldOptions_JSType_JS_STRING = 1,
+ FieldOptions_JSType_JS_NUMBER = 2
+};
+LIBPROTOBUF_EXPORT bool FieldOptions_JSType_IsValid(int value);
+const FieldOptions_JSType FieldOptions_JSType_JSType_MIN = FieldOptions_JSType_JS_NORMAL;
+const FieldOptions_JSType FieldOptions_JSType_JSType_MAX = FieldOptions_JSType_JS_NUMBER;
+const int FieldOptions_JSType_JSType_ARRAYSIZE = FieldOptions_JSType_JSType_MAX + 1;
+
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_JSType_descriptor();
+inline const ::std::string& FieldOptions_JSType_Name(FieldOptions_JSType value) {
+ return ::google::protobuf::internal::NameOfEnum(
+ FieldOptions_JSType_descriptor(), value);
+}
+inline bool FieldOptions_JSType_Parse(
+ const ::std::string& name, FieldOptions_JSType* value) {
+ return ::google::protobuf::internal::ParseNamedEnum<FieldOptions_JSType>(
+ FieldOptions_JSType_descriptor(), name, value);
+}
// ===================================================================
class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message {
@@ -222,15 +243,15 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
// accessors -------------------------------------------------------
// repeated .google.protobuf.FileDescriptorProto file = 1;
- inline int file_size() const;
- inline void clear_file();
+ int file_size() const;
+ void clear_file();
static const int kFileFieldNumber = 1;
- inline const ::google::protobuf::FileDescriptorProto& file(int index) const;
- inline ::google::protobuf::FileDescriptorProto* mutable_file(int index);
- inline ::google::protobuf::FileDescriptorProto* add_file();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+ const ::google::protobuf::FileDescriptorProto& file(int index) const;
+ ::google::protobuf::FileDescriptorProto* mutable_file(int index);
+ ::google::protobuf::FileDescriptorProto* add_file();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
file() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
mutable_file();
// @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet)
@@ -314,146 +335,146 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// optional string package = 2;
- inline bool has_package() const;
- inline void clear_package();
+ bool has_package() const;
+ void clear_package();
static const int kPackageFieldNumber = 2;
- inline const ::std::string& package() const;
- inline void set_package(const ::std::string& value);
- inline void set_package(const char* value);
- inline void set_package(const char* value, size_t size);
- inline ::std::string* mutable_package();
- inline ::std::string* release_package();
- inline void set_allocated_package(::std::string* package);
+ const ::std::string& package() const;
+ void set_package(const ::std::string& value);
+ void set_package(const char* value);
+ void set_package(const char* value, size_t size);
+ ::std::string* mutable_package();
+ ::std::string* release_package();
+ void set_allocated_package(::std::string* package);
// repeated string dependency = 3;
- inline int dependency_size() const;
- inline void clear_dependency();
+ int dependency_size() const;
+ void clear_dependency();
static const int kDependencyFieldNumber = 3;
- inline const ::std::string& dependency(int index) const;
- inline ::std::string* mutable_dependency(int index);
- inline void set_dependency(int index, const ::std::string& value);
- inline void set_dependency(int index, const char* value);
- inline void set_dependency(int index, const char* value, size_t size);
- inline ::std::string* add_dependency();
- inline void add_dependency(const ::std::string& value);
- inline void add_dependency(const char* value);
- inline void add_dependency(const char* value, size_t size);
- inline const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const;
- inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency();
+ const ::std::string& dependency(int index) const;
+ ::std::string* mutable_dependency(int index);
+ void set_dependency(int index, const ::std::string& value);
+ void set_dependency(int index, const char* value);
+ void set_dependency(int index, const char* value, size_t size);
+ ::std::string* add_dependency();
+ void add_dependency(const ::std::string& value);
+ void add_dependency(const char* value);
+ void add_dependency(const char* value, size_t size);
+ const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const;
+ ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency();
// repeated int32 public_dependency = 10;
- inline int public_dependency_size() const;
- inline void clear_public_dependency();
+ int public_dependency_size() const;
+ void clear_public_dependency();
static const int kPublicDependencyFieldNumber = 10;
- inline ::google::protobuf::int32 public_dependency(int index) const;
- inline void set_public_dependency(int index, ::google::protobuf::int32 value);
- inline void add_public_dependency(::google::protobuf::int32 value);
- inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+ ::google::protobuf::int32 public_dependency(int index) const;
+ void set_public_dependency(int index, ::google::protobuf::int32 value);
+ void add_public_dependency(::google::protobuf::int32 value);
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
public_dependency() const;
- inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
mutable_public_dependency();
// repeated int32 weak_dependency = 11;
- inline int weak_dependency_size() const;
- inline void clear_weak_dependency();
+ int weak_dependency_size() const;
+ void clear_weak_dependency();
static const int kWeakDependencyFieldNumber = 11;
- inline ::google::protobuf::int32 weak_dependency(int index) const;
- inline void set_weak_dependency(int index, ::google::protobuf::int32 value);
- inline void add_weak_dependency(::google::protobuf::int32 value);
- inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+ ::google::protobuf::int32 weak_dependency(int index) const;
+ void set_weak_dependency(int index, ::google::protobuf::int32 value);
+ void add_weak_dependency(::google::protobuf::int32 value);
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
weak_dependency() const;
- inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
mutable_weak_dependency();
// repeated .google.protobuf.DescriptorProto message_type = 4;
- inline int message_type_size() const;
- inline void clear_message_type();
+ int message_type_size() const;
+ void clear_message_type();
static const int kMessageTypeFieldNumber = 4;
- inline const ::google::protobuf::DescriptorProto& message_type(int index) const;
- inline ::google::protobuf::DescriptorProto* mutable_message_type(int index);
- inline ::google::protobuf::DescriptorProto* add_message_type();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+ const ::google::protobuf::DescriptorProto& message_type(int index) const;
+ ::google::protobuf::DescriptorProto* mutable_message_type(int index);
+ ::google::protobuf::DescriptorProto* add_message_type();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
message_type() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
mutable_message_type();
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
- inline int enum_type_size() const;
- inline void clear_enum_type();
+ int enum_type_size() const;
+ void clear_enum_type();
static const int kEnumTypeFieldNumber = 5;
- inline const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
- inline ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
- inline ::google::protobuf::EnumDescriptorProto* add_enum_type();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+ const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
+ ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
+ ::google::protobuf::EnumDescriptorProto* add_enum_type();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
enum_type() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
mutable_enum_type();
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
- inline int service_size() const;
- inline void clear_service();
+ int service_size() const;
+ void clear_service();
static const int kServiceFieldNumber = 6;
- inline const ::google::protobuf::ServiceDescriptorProto& service(int index) const;
- inline ::google::protobuf::ServiceDescriptorProto* mutable_service(int index);
- inline ::google::protobuf::ServiceDescriptorProto* add_service();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+ const ::google::protobuf::ServiceDescriptorProto& service(int index) const;
+ ::google::protobuf::ServiceDescriptorProto* mutable_service(int index);
+ ::google::protobuf::ServiceDescriptorProto* add_service();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
service() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
mutable_service();
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
- inline int extension_size() const;
- inline void clear_extension();
+ int extension_size() const;
+ void clear_extension();
static const int kExtensionFieldNumber = 7;
- inline const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
- inline ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
- inline ::google::protobuf::FieldDescriptorProto* add_extension();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
+ ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
+ ::google::protobuf::FieldDescriptorProto* add_extension();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
extension() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
mutable_extension();
// optional .google.protobuf.FileOptions options = 8;
- inline bool has_options() const;
- inline void clear_options();
+ bool has_options() const;
+ void clear_options();
static const int kOptionsFieldNumber = 8;
- inline const ::google::protobuf::FileOptions& options() const;
- inline ::google::protobuf::FileOptions* mutable_options();
- inline ::google::protobuf::FileOptions* release_options();
- inline void set_allocated_options(::google::protobuf::FileOptions* options);
+ const ::google::protobuf::FileOptions& options() const;
+ ::google::protobuf::FileOptions* mutable_options();
+ ::google::protobuf::FileOptions* release_options();
+ void set_allocated_options(::google::protobuf::FileOptions* options);
// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
- inline bool has_source_code_info() const;
- inline void clear_source_code_info();
+ bool has_source_code_info() const;
+ void clear_source_code_info();
static const int kSourceCodeInfoFieldNumber = 9;
- inline const ::google::protobuf::SourceCodeInfo& source_code_info() const;
- inline ::google::protobuf::SourceCodeInfo* mutable_source_code_info();
- inline ::google::protobuf::SourceCodeInfo* release_source_code_info();
- inline void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info);
+ const ::google::protobuf::SourceCodeInfo& source_code_info() const;
+ ::google::protobuf::SourceCodeInfo* mutable_source_code_info();
+ ::google::protobuf::SourceCodeInfo* release_source_code_info();
+ void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info);
// optional string syntax = 12;
- inline bool has_syntax() const;
- inline void clear_syntax();
+ bool has_syntax() const;
+ void clear_syntax();
static const int kSyntaxFieldNumber = 12;
- inline const ::std::string& syntax() const;
- inline void set_syntax(const ::std::string& value);
- inline void set_syntax(const char* value);
- inline void set_syntax(const char* value, size_t size);
- inline ::std::string* mutable_syntax();
- inline ::std::string* release_syntax();
- inline void set_allocated_syntax(::std::string* syntax);
+ const ::std::string& syntax() const;
+ void set_syntax(const ::std::string& value);
+ void set_syntax(const char* value);
+ void set_syntax(const char* value, size_t size);
+ ::std::string* mutable_syntax();
+ ::std::string* release_syntax();
+ void set_allocated_syntax(::std::string* syntax);
// @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto)
private:
@@ -557,18 +578,18 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
// accessors -------------------------------------------------------
// optional int32 start = 1;
- inline bool has_start() const;
- inline void clear_start();
+ bool has_start() const;
+ void clear_start();
static const int kStartFieldNumber = 1;
- inline ::google::protobuf::int32 start() const;
- inline void set_start(::google::protobuf::int32 value);
+ ::google::protobuf::int32 start() const;
+ void set_start(::google::protobuf::int32 value);
// optional int32 end = 2;
- inline bool has_end() const;
- inline void clear_end();
+ bool has_end() const;
+ void clear_end();
static const int kEndFieldNumber = 2;
- inline ::google::protobuf::int32 end() const;
- inline void set_end(::google::protobuf::int32 value);
+ ::google::protobuf::int32 end() const;
+ void set_end(::google::protobuf::int32 value);
// @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange)
private:
@@ -591,6 +612,105 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
};
// -------------------------------------------------------------------
+class LIBPROTOBUF_EXPORT DescriptorProto_ReservedRange : public ::google::protobuf::Message {
+ public:
+ DescriptorProto_ReservedRange();
+ virtual ~DescriptorProto_ReservedRange();
+
+ DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from);
+
+ inline DescriptorProto_ReservedRange& operator=(const DescriptorProto_ReservedRange& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+ return _internal_metadata_.unknown_fields();
+ }
+
+ inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+ return _internal_metadata_.mutable_unknown_fields();
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const DescriptorProto_ReservedRange& default_instance();
+
+ void Swap(DescriptorProto_ReservedRange* other);
+
+ // implements Message ----------------------------------------------
+
+ inline DescriptorProto_ReservedRange* New() const { return New(NULL); }
+
+ DescriptorProto_ReservedRange* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const DescriptorProto_ReservedRange& from);
+ void MergeFrom(const DescriptorProto_ReservedRange& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(DescriptorProto_ReservedRange* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional int32 start = 1;
+ bool has_start() const;
+ void clear_start();
+ static const int kStartFieldNumber = 1;
+ ::google::protobuf::int32 start() const;
+ void set_start(::google::protobuf::int32 value);
+
+ // optional int32 end = 2;
+ bool has_end() const;
+ void clear_end();
+ static const int kEndFieldNumber = 2;
+ ::google::protobuf::int32 end() const;
+ void set_end(::google::protobuf::int32 value);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ReservedRange)
+ private:
+ inline void set_has_start();
+ inline void clear_has_start();
+ inline void set_has_end();
+ inline void clear_has_end();
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ ::google::protobuf::uint32 _has_bits_[1];
+ mutable int _cached_size_;
+ ::google::protobuf::int32 start_;
+ ::google::protobuf::int32 end_;
+ 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();
+
+ void InitAsDefaultInstance();
+ static DescriptorProto_ReservedRange* default_instance_;
+};
+// -------------------------------------------------------------------
+
class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
public:
DescriptorProto();
@@ -654,101 +774,130 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
// nested types ----------------------------------------------------
typedef DescriptorProto_ExtensionRange ExtensionRange;
+ typedef DescriptorProto_ReservedRange ReservedRange;
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// repeated .google.protobuf.FieldDescriptorProto field = 2;
- inline int field_size() const;
- inline void clear_field();
+ int field_size() const;
+ void clear_field();
static const int kFieldFieldNumber = 2;
- inline const ::google::protobuf::FieldDescriptorProto& field(int index) const;
- inline ::google::protobuf::FieldDescriptorProto* mutable_field(int index);
- inline ::google::protobuf::FieldDescriptorProto* add_field();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ const ::google::protobuf::FieldDescriptorProto& field(int index) const;
+ ::google::protobuf::FieldDescriptorProto* mutable_field(int index);
+ ::google::protobuf::FieldDescriptorProto* add_field();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
field() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
mutable_field();
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
- inline int extension_size() const;
- inline void clear_extension();
+ int extension_size() const;
+ void clear_extension();
static const int kExtensionFieldNumber = 6;
- inline const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
- inline ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
- inline ::google::protobuf::FieldDescriptorProto* add_extension();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
+ ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
+ ::google::protobuf::FieldDescriptorProto* add_extension();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
extension() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
mutable_extension();
// repeated .google.protobuf.DescriptorProto nested_type = 3;
- inline int nested_type_size() const;
- inline void clear_nested_type();
+ int nested_type_size() const;
+ void clear_nested_type();
static const int kNestedTypeFieldNumber = 3;
- inline const ::google::protobuf::DescriptorProto& nested_type(int index) const;
- inline ::google::protobuf::DescriptorProto* mutable_nested_type(int index);
- inline ::google::protobuf::DescriptorProto* add_nested_type();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+ const ::google::protobuf::DescriptorProto& nested_type(int index) const;
+ ::google::protobuf::DescriptorProto* mutable_nested_type(int index);
+ ::google::protobuf::DescriptorProto* add_nested_type();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
nested_type() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
mutable_nested_type();
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
- inline int enum_type_size() const;
- inline void clear_enum_type();
+ int enum_type_size() const;
+ void clear_enum_type();
static const int kEnumTypeFieldNumber = 4;
- inline const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
- inline ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
- inline ::google::protobuf::EnumDescriptorProto* add_enum_type();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+ const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
+ ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
+ ::google::protobuf::EnumDescriptorProto* add_enum_type();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
enum_type() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
mutable_enum_type();
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
- inline int extension_range_size() const;
- inline void clear_extension_range();
+ int extension_range_size() const;
+ void clear_extension_range();
static const int kExtensionRangeFieldNumber = 5;
- inline const ::google::protobuf::DescriptorProto_ExtensionRange& extension_range(int index) const;
- inline ::google::protobuf::DescriptorProto_ExtensionRange* mutable_extension_range(int index);
- inline ::google::protobuf::DescriptorProto_ExtensionRange* add_extension_range();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+ const ::google::protobuf::DescriptorProto_ExtensionRange& extension_range(int index) const;
+ ::google::protobuf::DescriptorProto_ExtensionRange* mutable_extension_range(int index);
+ ::google::protobuf::DescriptorProto_ExtensionRange* add_extension_range();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
extension_range() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
mutable_extension_range();
// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
- inline int oneof_decl_size() const;
- inline void clear_oneof_decl();
+ int oneof_decl_size() const;
+ void clear_oneof_decl();
static const int kOneofDeclFieldNumber = 8;
- inline const ::google::protobuf::OneofDescriptorProto& oneof_decl(int index) const;
- inline ::google::protobuf::OneofDescriptorProto* mutable_oneof_decl(int index);
- inline ::google::protobuf::OneofDescriptorProto* add_oneof_decl();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
+ const ::google::protobuf::OneofDescriptorProto& oneof_decl(int index) const;
+ ::google::protobuf::OneofDescriptorProto* mutable_oneof_decl(int index);
+ ::google::protobuf::OneofDescriptorProto* add_oneof_decl();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
oneof_decl() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
mutable_oneof_decl();
// optional .google.protobuf.MessageOptions options = 7;
- inline bool has_options() const;
- inline void clear_options();
+ bool has_options() const;
+ void clear_options();
static const int kOptionsFieldNumber = 7;
- inline const ::google::protobuf::MessageOptions& options() const;
- inline ::google::protobuf::MessageOptions* mutable_options();
- inline ::google::protobuf::MessageOptions* release_options();
- inline void set_allocated_options(::google::protobuf::MessageOptions* options);
+ const ::google::protobuf::MessageOptions& options() const;
+ ::google::protobuf::MessageOptions* mutable_options();
+ ::google::protobuf::MessageOptions* release_options();
+ void set_allocated_options(::google::protobuf::MessageOptions* options);
+
+ // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+ int reserved_range_size() const;
+ void clear_reserved_range();
+ static const int kReservedRangeFieldNumber = 9;
+ const ::google::protobuf::DescriptorProto_ReservedRange& reserved_range(int index) const;
+ ::google::protobuf::DescriptorProto_ReservedRange* mutable_reserved_range(int index);
+ ::google::protobuf::DescriptorProto_ReservedRange* add_reserved_range();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
+ reserved_range() const;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
+ mutable_reserved_range();
+
+ // repeated string reserved_name = 10;
+ int reserved_name_size() const;
+ void clear_reserved_name();
+ static const int kReservedNameFieldNumber = 10;
+ const ::std::string& reserved_name(int index) const;
+ ::std::string* mutable_reserved_name(int index);
+ void set_reserved_name(int index, const ::std::string& value);
+ void set_reserved_name(int index, const char* value);
+ void set_reserved_name(int index, const char* value, size_t size);
+ ::std::string* add_reserved_name();
+ void add_reserved_name(const ::std::string& value);
+ void add_reserved_name(const char* value);
+ void add_reserved_name(const char* value, size_t size);
+ const ::google::protobuf::RepeatedPtrField< ::std::string>& reserved_name() const;
+ ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_reserved_name();
// @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto)
private:
@@ -768,6 +917,8 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange > extension_range_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto > oneof_decl_;
::google::protobuf::MessageOptions* options_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange > reserved_range_;
+ ::google::protobuf::RepeatedPtrField< ::std::string> reserved_name_;
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();
@@ -907,89 +1058,89 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// optional int32 number = 3;
- inline bool has_number() const;
- inline void clear_number();
+ bool has_number() const;
+ void clear_number();
static const int kNumberFieldNumber = 3;
- inline ::google::protobuf::int32 number() const;
- inline void set_number(::google::protobuf::int32 value);
+ ::google::protobuf::int32 number() const;
+ void set_number(::google::protobuf::int32 value);
// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
- inline bool has_label() const;
- inline void clear_label();
+ bool has_label() const;
+ void clear_label();
static const int kLabelFieldNumber = 4;
- inline ::google::protobuf::FieldDescriptorProto_Label label() const;
- inline void set_label(::google::protobuf::FieldDescriptorProto_Label value);
+ ::google::protobuf::FieldDescriptorProto_Label label() const;
+ void set_label(::google::protobuf::FieldDescriptorProto_Label value);
// optional .google.protobuf.FieldDescriptorProto.Type type = 5;
- inline bool has_type() const;
- inline void clear_type();
+ bool has_type() const;
+ void clear_type();
static const int kTypeFieldNumber = 5;
- inline ::google::protobuf::FieldDescriptorProto_Type type() const;
- inline void set_type(::google::protobuf::FieldDescriptorProto_Type value);
+ ::google::protobuf::FieldDescriptorProto_Type type() const;
+ void set_type(::google::protobuf::FieldDescriptorProto_Type value);
// optional string type_name = 6;
- inline bool has_type_name() const;
- inline void clear_type_name();
+ bool has_type_name() const;
+ void clear_type_name();
static const int kTypeNameFieldNumber = 6;
- inline const ::std::string& type_name() const;
- inline void set_type_name(const ::std::string& value);
- inline void set_type_name(const char* value);
- inline void set_type_name(const char* value, size_t size);
- inline ::std::string* mutable_type_name();
- inline ::std::string* release_type_name();
- inline void set_allocated_type_name(::std::string* type_name);
+ const ::std::string& type_name() const;
+ void set_type_name(const ::std::string& value);
+ void set_type_name(const char* value);
+ void set_type_name(const char* value, size_t size);
+ ::std::string* mutable_type_name();
+ ::std::string* release_type_name();
+ void set_allocated_type_name(::std::string* type_name);
// optional string extendee = 2;
- inline bool has_extendee() const;
- inline void clear_extendee();
+ bool has_extendee() const;
+ void clear_extendee();
static const int kExtendeeFieldNumber = 2;
- inline const ::std::string& extendee() const;
- inline void set_extendee(const ::std::string& value);
- inline void set_extendee(const char* value);
- inline void set_extendee(const char* value, size_t size);
- inline ::std::string* mutable_extendee();
- inline ::std::string* release_extendee();
- inline void set_allocated_extendee(::std::string* extendee);
+ const ::std::string& extendee() const;
+ void set_extendee(const ::std::string& value);
+ void set_extendee(const char* value);
+ void set_extendee(const char* value, size_t size);
+ ::std::string* mutable_extendee();
+ ::std::string* release_extendee();
+ void set_allocated_extendee(::std::string* extendee);
// optional string default_value = 7;
- inline bool has_default_value() const;
- inline void clear_default_value();
+ bool has_default_value() const;
+ void clear_default_value();
static const int kDefaultValueFieldNumber = 7;
- inline const ::std::string& default_value() const;
- inline void set_default_value(const ::std::string& value);
- inline void set_default_value(const char* value);
- inline void set_default_value(const char* value, size_t size);
- inline ::std::string* mutable_default_value();
- inline ::std::string* release_default_value();
- inline void set_allocated_default_value(::std::string* default_value);
+ const ::std::string& default_value() const;
+ void set_default_value(const ::std::string& value);
+ void set_default_value(const char* value);
+ void set_default_value(const char* value, size_t size);
+ ::std::string* mutable_default_value();
+ ::std::string* release_default_value();
+ void set_allocated_default_value(::std::string* default_value);
// optional int32 oneof_index = 9;
- inline bool has_oneof_index() const;
- inline void clear_oneof_index();
+ bool has_oneof_index() const;
+ void clear_oneof_index();
static const int kOneofIndexFieldNumber = 9;
- inline ::google::protobuf::int32 oneof_index() const;
- inline void set_oneof_index(::google::protobuf::int32 value);
+ ::google::protobuf::int32 oneof_index() const;
+ void set_oneof_index(::google::protobuf::int32 value);
// optional .google.protobuf.FieldOptions options = 8;
- inline bool has_options() const;
- inline void clear_options();
+ bool has_options() const;
+ void clear_options();
static const int kOptionsFieldNumber = 8;
- inline const ::google::protobuf::FieldOptions& options() const;
- inline ::google::protobuf::FieldOptions* mutable_options();
- inline ::google::protobuf::FieldOptions* release_options();
- inline void set_allocated_options(::google::protobuf::FieldOptions* options);
+ const ::google::protobuf::FieldOptions& options() const;
+ ::google::protobuf::FieldOptions* mutable_options();
+ ::google::protobuf::FieldOptions* release_options();
+ void set_allocated_options(::google::protobuf::FieldOptions* options);
// @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto)
private:
@@ -1098,16 +1249,16 @@ class LIBPROTOBUF_EXPORT OneofDescriptorProto : public ::google::protobuf::Messa
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// @@protoc_insertion_point(class_scope:google.protobuf.OneofDescriptorProto)
private:
@@ -1192,37 +1343,37 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
- inline int value_size() const;
- inline void clear_value();
+ int value_size() const;
+ void clear_value();
static const int kValueFieldNumber = 2;
- inline const ::google::protobuf::EnumValueDescriptorProto& value(int index) const;
- inline ::google::protobuf::EnumValueDescriptorProto* mutable_value(int index);
- inline ::google::protobuf::EnumValueDescriptorProto* add_value();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+ const ::google::protobuf::EnumValueDescriptorProto& value(int index) const;
+ ::google::protobuf::EnumValueDescriptorProto* mutable_value(int index);
+ ::google::protobuf::EnumValueDescriptorProto* add_value();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
value() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
mutable_value();
// optional .google.protobuf.EnumOptions options = 3;
- inline bool has_options() const;
- inline void clear_options();
+ bool has_options() const;
+ void clear_options();
static const int kOptionsFieldNumber = 3;
- inline const ::google::protobuf::EnumOptions& options() const;
- inline ::google::protobuf::EnumOptions* mutable_options();
- inline ::google::protobuf::EnumOptions* release_options();
- inline void set_allocated_options(::google::protobuf::EnumOptions* options);
+ const ::google::protobuf::EnumOptions& options() const;
+ ::google::protobuf::EnumOptions* mutable_options();
+ ::google::protobuf::EnumOptions* release_options();
+ void set_allocated_options(::google::protobuf::EnumOptions* options);
// @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto)
private:
@@ -1311,32 +1462,32 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// optional int32 number = 2;
- inline bool has_number() const;
- inline void clear_number();
+ bool has_number() const;
+ void clear_number();
static const int kNumberFieldNumber = 2;
- inline ::google::protobuf::int32 number() const;
- inline void set_number(::google::protobuf::int32 value);
+ ::google::protobuf::int32 number() const;
+ void set_number(::google::protobuf::int32 value);
// optional .google.protobuf.EnumValueOptions options = 3;
- inline bool has_options() const;
- inline void clear_options();
+ bool has_options() const;
+ void clear_options();
static const int kOptionsFieldNumber = 3;
- inline const ::google::protobuf::EnumValueOptions& options() const;
- inline ::google::protobuf::EnumValueOptions* mutable_options();
- inline ::google::protobuf::EnumValueOptions* release_options();
- inline void set_allocated_options(::google::protobuf::EnumValueOptions* options);
+ const ::google::protobuf::EnumValueOptions& options() const;
+ ::google::protobuf::EnumValueOptions* mutable_options();
+ ::google::protobuf::EnumValueOptions* release_options();
+ void set_allocated_options(::google::protobuf::EnumValueOptions* options);
// @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto)
private:
@@ -1427,37 +1578,37 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// repeated .google.protobuf.MethodDescriptorProto method = 2;
- inline int method_size() const;
- inline void clear_method();
+ int method_size() const;
+ void clear_method();
static const int kMethodFieldNumber = 2;
- inline const ::google::protobuf::MethodDescriptorProto& method(int index) const;
- inline ::google::protobuf::MethodDescriptorProto* mutable_method(int index);
- inline ::google::protobuf::MethodDescriptorProto* add_method();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ const ::google::protobuf::MethodDescriptorProto& method(int index) const;
+ ::google::protobuf::MethodDescriptorProto* mutable_method(int index);
+ ::google::protobuf::MethodDescriptorProto* add_method();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
method() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
mutable_method();
// optional .google.protobuf.ServiceOptions options = 3;
- inline bool has_options() const;
- inline void clear_options();
+ bool has_options() const;
+ void clear_options();
static const int kOptionsFieldNumber = 3;
- inline const ::google::protobuf::ServiceOptions& options() const;
- inline ::google::protobuf::ServiceOptions* mutable_options();
- inline ::google::protobuf::ServiceOptions* release_options();
- inline void set_allocated_options(::google::protobuf::ServiceOptions* options);
+ const ::google::protobuf::ServiceOptions& options() const;
+ ::google::protobuf::ServiceOptions* mutable_options();
+ ::google::protobuf::ServiceOptions* release_options();
+ void set_allocated_options(::google::protobuf::ServiceOptions* options);
// @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto)
private:
@@ -1546,63 +1697,63 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// optional string input_type = 2;
- inline bool has_input_type() const;
- inline void clear_input_type();
+ bool has_input_type() const;
+ void clear_input_type();
static const int kInputTypeFieldNumber = 2;
- inline const ::std::string& input_type() const;
- inline void set_input_type(const ::std::string& value);
- inline void set_input_type(const char* value);
- inline void set_input_type(const char* value, size_t size);
- inline ::std::string* mutable_input_type();
- inline ::std::string* release_input_type();
- inline void set_allocated_input_type(::std::string* input_type);
+ const ::std::string& input_type() const;
+ void set_input_type(const ::std::string& value);
+ void set_input_type(const char* value);
+ void set_input_type(const char* value, size_t size);
+ ::std::string* mutable_input_type();
+ ::std::string* release_input_type();
+ void set_allocated_input_type(::std::string* input_type);
// optional string output_type = 3;
- inline bool has_output_type() const;
- inline void clear_output_type();
+ bool has_output_type() const;
+ void clear_output_type();
static const int kOutputTypeFieldNumber = 3;
- inline const ::std::string& output_type() const;
- inline void set_output_type(const ::std::string& value);
- inline void set_output_type(const char* value);
- inline void set_output_type(const char* value, size_t size);
- inline ::std::string* mutable_output_type();
- inline ::std::string* release_output_type();
- inline void set_allocated_output_type(::std::string* output_type);
+ const ::std::string& output_type() const;
+ void set_output_type(const ::std::string& value);
+ void set_output_type(const char* value);
+ void set_output_type(const char* value, size_t size);
+ ::std::string* mutable_output_type();
+ ::std::string* release_output_type();
+ void set_allocated_output_type(::std::string* output_type);
// optional .google.protobuf.MethodOptions options = 4;
- inline bool has_options() const;
- inline void clear_options();
+ bool has_options() const;
+ void clear_options();
static const int kOptionsFieldNumber = 4;
- inline const ::google::protobuf::MethodOptions& options() const;
- inline ::google::protobuf::MethodOptions* mutable_options();
- inline ::google::protobuf::MethodOptions* release_options();
- inline void set_allocated_options(::google::protobuf::MethodOptions* options);
+ const ::google::protobuf::MethodOptions& options() const;
+ ::google::protobuf::MethodOptions* mutable_options();
+ ::google::protobuf::MethodOptions* release_options();
+ void set_allocated_options(::google::protobuf::MethodOptions* options);
// optional bool client_streaming = 5 [default = false];
- inline bool has_client_streaming() const;
- inline void clear_client_streaming();
+ bool has_client_streaming() const;
+ void clear_client_streaming();
static const int kClientStreamingFieldNumber = 5;
- inline bool client_streaming() const;
- inline void set_client_streaming(bool value);
+ bool client_streaming() const;
+ void set_client_streaming(bool value);
// optional bool server_streaming = 6 [default = false];
- inline bool has_server_streaming() const;
- inline void clear_server_streaming();
+ bool has_server_streaming() const;
+ void clear_server_streaming();
static const int kServerStreamingFieldNumber = 6;
- inline bool server_streaming() const;
- inline void set_server_streaming(bool value);
+ bool server_streaming() const;
+ void set_server_streaming(bool value);
// @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto)
private:
@@ -1727,114 +1878,145 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
// optional string java_package = 1;
- inline bool has_java_package() const;
- inline void clear_java_package();
+ bool has_java_package() const;
+ void clear_java_package();
static const int kJavaPackageFieldNumber = 1;
- inline const ::std::string& java_package() const;
- inline void set_java_package(const ::std::string& value);
- inline void set_java_package(const char* value);
- inline void set_java_package(const char* value, size_t size);
- inline ::std::string* mutable_java_package();
- inline ::std::string* release_java_package();
- inline void set_allocated_java_package(::std::string* java_package);
+ const ::std::string& java_package() const;
+ void set_java_package(const ::std::string& value);
+ void set_java_package(const char* value);
+ void set_java_package(const char* value, size_t size);
+ ::std::string* mutable_java_package();
+ ::std::string* release_java_package();
+ void set_allocated_java_package(::std::string* java_package);
// optional string java_outer_classname = 8;
- inline bool has_java_outer_classname() const;
- inline void clear_java_outer_classname();
+ bool has_java_outer_classname() const;
+ void clear_java_outer_classname();
static const int kJavaOuterClassnameFieldNumber = 8;
- inline const ::std::string& java_outer_classname() const;
- inline void set_java_outer_classname(const ::std::string& value);
- inline void set_java_outer_classname(const char* value);
- inline void set_java_outer_classname(const char* value, size_t size);
- inline ::std::string* mutable_java_outer_classname();
- inline ::std::string* release_java_outer_classname();
- inline void set_allocated_java_outer_classname(::std::string* java_outer_classname);
+ const ::std::string& java_outer_classname() const;
+ void set_java_outer_classname(const ::std::string& value);
+ void set_java_outer_classname(const char* value);
+ void set_java_outer_classname(const char* value, size_t size);
+ ::std::string* mutable_java_outer_classname();
+ ::std::string* release_java_outer_classname();
+ void set_allocated_java_outer_classname(::std::string* java_outer_classname);
// optional bool java_multiple_files = 10 [default = false];
- inline bool has_java_multiple_files() const;
- inline void clear_java_multiple_files();
+ bool has_java_multiple_files() const;
+ void clear_java_multiple_files();
static const int kJavaMultipleFilesFieldNumber = 10;
- inline bool java_multiple_files() const;
- inline void set_java_multiple_files(bool value);
+ bool java_multiple_files() const;
+ void set_java_multiple_files(bool value);
// optional bool java_generate_equals_and_hash = 20 [default = false];
- inline bool has_java_generate_equals_and_hash() const;
- inline void clear_java_generate_equals_and_hash();
+ bool has_java_generate_equals_and_hash() const;
+ void clear_java_generate_equals_and_hash();
static const int kJavaGenerateEqualsAndHashFieldNumber = 20;
- inline bool java_generate_equals_and_hash() const;
- inline void set_java_generate_equals_and_hash(bool value);
+ bool java_generate_equals_and_hash() const;
+ void set_java_generate_equals_and_hash(bool value);
// optional bool java_string_check_utf8 = 27 [default = false];
- inline bool has_java_string_check_utf8() const;
- inline void clear_java_string_check_utf8();
+ bool has_java_string_check_utf8() const;
+ void clear_java_string_check_utf8();
static const int kJavaStringCheckUtf8FieldNumber = 27;
- inline bool java_string_check_utf8() const;
- inline void set_java_string_check_utf8(bool value);
+ bool java_string_check_utf8() const;
+ void set_java_string_check_utf8(bool value);
// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
- inline bool has_optimize_for() const;
- inline void clear_optimize_for();
+ bool has_optimize_for() const;
+ void clear_optimize_for();
static const int kOptimizeForFieldNumber = 9;
- inline ::google::protobuf::FileOptions_OptimizeMode optimize_for() const;
- inline void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value);
+ ::google::protobuf::FileOptions_OptimizeMode optimize_for() const;
+ void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value);
// optional string go_package = 11;
- inline bool has_go_package() const;
- inline void clear_go_package();
+ bool has_go_package() const;
+ void clear_go_package();
static const int kGoPackageFieldNumber = 11;
- inline const ::std::string& go_package() const;
- inline void set_go_package(const ::std::string& value);
- inline void set_go_package(const char* value);
- inline void set_go_package(const char* value, size_t size);
- inline ::std::string* mutable_go_package();
- inline ::std::string* release_go_package();
- inline void set_allocated_go_package(::std::string* go_package);
+ const ::std::string& go_package() const;
+ void set_go_package(const ::std::string& value);
+ void set_go_package(const char* value);
+ void set_go_package(const char* value, size_t size);
+ ::std::string* mutable_go_package();
+ ::std::string* release_go_package();
+ void set_allocated_go_package(::std::string* go_package);
// optional bool cc_generic_services = 16 [default = false];
- inline bool has_cc_generic_services() const;
- inline void clear_cc_generic_services();
+ bool has_cc_generic_services() const;
+ void clear_cc_generic_services();
static const int kCcGenericServicesFieldNumber = 16;
- inline bool cc_generic_services() const;
- inline void set_cc_generic_services(bool value);
+ bool cc_generic_services() const;
+ void set_cc_generic_services(bool value);
// optional bool java_generic_services = 17 [default = false];
- inline bool has_java_generic_services() const;
- inline void clear_java_generic_services();
+ bool has_java_generic_services() const;
+ void clear_java_generic_services();
static const int kJavaGenericServicesFieldNumber = 17;
- inline bool java_generic_services() const;
- inline void set_java_generic_services(bool value);
+ bool java_generic_services() const;
+ void set_java_generic_services(bool value);
// optional bool py_generic_services = 18 [default = false];
- inline bool has_py_generic_services() const;
- inline void clear_py_generic_services();
+ bool has_py_generic_services() const;
+ void clear_py_generic_services();
static const int kPyGenericServicesFieldNumber = 18;
- inline bool py_generic_services() const;
- inline void set_py_generic_services(bool value);
+ bool py_generic_services() const;
+ void set_py_generic_services(bool value);
// optional bool deprecated = 23 [default = false];
- inline bool has_deprecated() const;
- inline void clear_deprecated();
+ bool has_deprecated() const;
+ void clear_deprecated();
static const int kDeprecatedFieldNumber = 23;
- inline bool deprecated() const;
- inline void set_deprecated(bool value);
+ bool deprecated() const;
+ void set_deprecated(bool value);
// optional bool cc_enable_arenas = 31 [default = false];
- inline bool has_cc_enable_arenas() const;
- inline void clear_cc_enable_arenas();
+ bool has_cc_enable_arenas() const;
+ void clear_cc_enable_arenas();
static const int kCcEnableArenasFieldNumber = 31;
- inline bool cc_enable_arenas() const;
- inline void set_cc_enable_arenas(bool value);
+ bool cc_enable_arenas() const;
+ void set_cc_enable_arenas(bool value);
+
+ // optional string objc_class_prefix = 36;
+ bool has_objc_class_prefix() const;
+ void clear_objc_class_prefix();
+ static const int kObjcClassPrefixFieldNumber = 36;
+ const ::std::string& objc_class_prefix() const;
+ void set_objc_class_prefix(const ::std::string& value);
+ void set_objc_class_prefix(const char* value);
+ void set_objc_class_prefix(const char* value, size_t size);
+ ::std::string* mutable_objc_class_prefix();
+ ::std::string* release_objc_class_prefix();
+ void set_allocated_objc_class_prefix(::std::string* objc_class_prefix);
+
+ // optional string csharp_namespace = 37;
+ bool has_csharp_namespace() const;
+ void clear_csharp_namespace();
+ static const int kCsharpNamespaceFieldNumber = 37;
+ const ::std::string& csharp_namespace() const;
+ void set_csharp_namespace(const ::std::string& value);
+ void set_csharp_namespace(const char* value);
+ void set_csharp_namespace(const char* value, size_t size);
+ ::std::string* mutable_csharp_namespace();
+ ::std::string* release_csharp_namespace();
+ void set_allocated_csharp_namespace(::std::string* csharp_namespace);
+
+ // optional bool javanano_use_deprecated_package = 38;
+ bool has_javanano_use_deprecated_package() const;
+ void clear_javanano_use_deprecated_package();
+ static const int kJavananoUseDeprecatedPackageFieldNumber = 38;
+ bool javanano_use_deprecated_package() const;
+ void set_javanano_use_deprecated_package(bool value);
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- inline int uninterpreted_option_size() const;
- inline void clear_uninterpreted_option();
+ int uninterpreted_option_size() const;
+ void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
- inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
- inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+ ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+ ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions)
@@ -1864,6 +2046,12 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
inline void clear_has_deprecated();
inline void set_has_cc_enable_arenas();
inline void clear_has_cc_enable_arenas();
+ inline void set_has_objc_class_prefix();
+ inline void clear_has_objc_class_prefix();
+ 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_;
@@ -1878,11 +2066,14 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
bool cc_generic_services_;
int optimize_for_;
::google::protobuf::internal::ArenaStringPtr go_package_;
- ::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();
@@ -1957,43 +2148,43 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
// optional bool message_set_wire_format = 1 [default = false];
- inline bool has_message_set_wire_format() const;
- inline void clear_message_set_wire_format();
+ bool has_message_set_wire_format() const;
+ void clear_message_set_wire_format();
static const int kMessageSetWireFormatFieldNumber = 1;
- inline bool message_set_wire_format() const;
- inline void set_message_set_wire_format(bool value);
+ bool message_set_wire_format() const;
+ void set_message_set_wire_format(bool value);
// optional bool no_standard_descriptor_accessor = 2 [default = false];
- inline bool has_no_standard_descriptor_accessor() const;
- inline void clear_no_standard_descriptor_accessor();
+ bool has_no_standard_descriptor_accessor() const;
+ void clear_no_standard_descriptor_accessor();
static const int kNoStandardDescriptorAccessorFieldNumber = 2;
- inline bool no_standard_descriptor_accessor() const;
- inline void set_no_standard_descriptor_accessor(bool value);
+ bool no_standard_descriptor_accessor() const;
+ void set_no_standard_descriptor_accessor(bool value);
// optional bool deprecated = 3 [default = false];
- inline bool has_deprecated() const;
- inline void clear_deprecated();
+ bool has_deprecated() const;
+ void clear_deprecated();
static const int kDeprecatedFieldNumber = 3;
- inline bool deprecated() const;
- inline void set_deprecated(bool value);
+ bool deprecated() const;
+ void set_deprecated(bool value);
// optional bool map_entry = 7;
- inline bool has_map_entry() const;
- inline void clear_map_entry();
+ bool has_map_entry() const;
+ void clear_map_entry();
static const int kMapEntryFieldNumber = 7;
- inline bool map_entry() const;
- inline void set_map_entry(bool value);
+ bool map_entry() const;
+ void set_map_entry(bool value);
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- inline int uninterpreted_option_size() const;
- inline void clear_uninterpreted_option();
+ int uninterpreted_option_size() const;
+ void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
- inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
- inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+ ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+ ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions)
@@ -2114,53 +2305,85 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
return FieldOptions_CType_Parse(name, value);
}
+ 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 inline bool JSType_IsValid(int value) {
+ return FieldOptions_JSType_IsValid(value);
+ }
+ static const JSType JSType_MIN =
+ FieldOptions_JSType_JSType_MIN;
+ static const JSType JSType_MAX =
+ FieldOptions_JSType_JSType_MAX;
+ static const int JSType_ARRAYSIZE =
+ FieldOptions_JSType_JSType_ARRAYSIZE;
+ static inline const ::google::protobuf::EnumDescriptor*
+ JSType_descriptor() {
+ return FieldOptions_JSType_descriptor();
+ }
+ static inline const ::std::string& JSType_Name(JSType value) {
+ return FieldOptions_JSType_Name(value);
+ }
+ static inline bool JSType_Parse(const ::std::string& name,
+ JSType* value) {
+ return FieldOptions_JSType_Parse(name, value);
+ }
+
// accessors -------------------------------------------------------
// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
- inline bool has_ctype() const;
- inline void clear_ctype();
+ bool has_ctype() const;
+ void clear_ctype();
static const int kCtypeFieldNumber = 1;
- inline ::google::protobuf::FieldOptions_CType ctype() const;
- inline void set_ctype(::google::protobuf::FieldOptions_CType value);
+ ::google::protobuf::FieldOptions_CType ctype() const;
+ void set_ctype(::google::protobuf::FieldOptions_CType value);
// optional bool packed = 2;
- inline bool has_packed() const;
- inline void clear_packed();
+ bool has_packed() const;
+ void clear_packed();
static const int kPackedFieldNumber = 2;
- inline bool packed() const;
- inline void set_packed(bool value);
+ bool packed() const;
+ void set_packed(bool value);
+
+ // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+ bool has_jstype() const;
+ void clear_jstype();
+ static const int kJstypeFieldNumber = 6;
+ ::google::protobuf::FieldOptions_JSType jstype() const;
+ void set_jstype(::google::protobuf::FieldOptions_JSType value);
// optional bool lazy = 5 [default = false];
- inline bool has_lazy() const;
- inline void clear_lazy();
+ bool has_lazy() const;
+ void clear_lazy();
static const int kLazyFieldNumber = 5;
- inline bool lazy() const;
- inline void set_lazy(bool value);
+ bool lazy() const;
+ void set_lazy(bool value);
// optional bool deprecated = 3 [default = false];
- inline bool has_deprecated() const;
- inline void clear_deprecated();
+ bool has_deprecated() const;
+ void clear_deprecated();
static const int kDeprecatedFieldNumber = 3;
- inline bool deprecated() const;
- inline void set_deprecated(bool value);
+ bool deprecated() const;
+ void set_deprecated(bool value);
// optional bool weak = 10 [default = false];
- inline bool has_weak() const;
- inline void clear_weak();
+ bool has_weak() const;
+ void clear_weak();
static const int kWeakFieldNumber = 10;
- inline bool weak() const;
- inline void set_weak(bool value);
+ bool weak() const;
+ void set_weak(bool value);
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- inline int uninterpreted_option_size() const;
- inline void clear_uninterpreted_option();
+ int uninterpreted_option_size() const;
+ void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
- inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
- inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+ ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+ ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions)
@@ -2170,6 +2393,8 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
inline void clear_has_ctype();
inline void set_has_packed();
inline void clear_has_packed();
+ inline void set_has_jstype();
+ inline void clear_has_jstype();
inline void set_has_lazy();
inline void clear_has_lazy();
inline void set_has_deprecated();
@@ -2183,11 +2408,12 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
int ctype_;
+ int jstype_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
bool packed_;
bool lazy_;
bool deprecated_;
bool weak_;
- ::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();
@@ -2262,29 +2488,29 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
// optional bool allow_alias = 2;
- inline bool has_allow_alias() const;
- inline void clear_allow_alias();
+ bool has_allow_alias() const;
+ void clear_allow_alias();
static const int kAllowAliasFieldNumber = 2;
- inline bool allow_alias() const;
- inline void set_allow_alias(bool value);
+ bool allow_alias() const;
+ void set_allow_alias(bool value);
// optional bool deprecated = 3 [default = false];
- inline bool has_deprecated() const;
- inline void clear_deprecated();
+ bool has_deprecated() const;
+ void clear_deprecated();
static const int kDeprecatedFieldNumber = 3;
- inline bool deprecated() const;
- inline void set_deprecated(bool value);
+ bool deprecated() const;
+ void set_deprecated(bool value);
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- inline int uninterpreted_option_size() const;
- inline void clear_uninterpreted_option();
+ int uninterpreted_option_size() const;
+ void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
- inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
- inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+ ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+ ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions)
@@ -2377,22 +2603,22 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
// optional bool deprecated = 1 [default = false];
- inline bool has_deprecated() const;
- inline void clear_deprecated();
+ bool has_deprecated() const;
+ void clear_deprecated();
static const int kDeprecatedFieldNumber = 1;
- inline bool deprecated() const;
- inline void set_deprecated(bool value);
+ bool deprecated() const;
+ void set_deprecated(bool value);
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- inline int uninterpreted_option_size() const;
- inline void clear_uninterpreted_option();
+ int uninterpreted_option_size() const;
+ void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
- inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
- inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+ ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+ ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions)
@@ -2482,22 +2708,22 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
// optional bool deprecated = 33 [default = false];
- inline bool has_deprecated() const;
- inline void clear_deprecated();
+ bool has_deprecated() const;
+ void clear_deprecated();
static const int kDeprecatedFieldNumber = 33;
- inline bool deprecated() const;
- inline void set_deprecated(bool value);
+ bool deprecated() const;
+ void set_deprecated(bool value);
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- inline int uninterpreted_option_size() const;
- inline void clear_uninterpreted_option();
+ int uninterpreted_option_size() const;
+ void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
- inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
- inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+ ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+ ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions)
@@ -2587,22 +2813,22 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
// optional bool deprecated = 33 [default = false];
- inline bool has_deprecated() const;
- inline void clear_deprecated();
+ bool has_deprecated() const;
+ void clear_deprecated();
static const int kDeprecatedFieldNumber = 33;
- inline bool deprecated() const;
- inline void set_deprecated(bool value);
+ bool deprecated() const;
+ void set_deprecated(bool value);
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- inline int uninterpreted_option_size() const;
- inline void clear_uninterpreted_option();
+ int uninterpreted_option_size() const;
+ void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
- inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
- inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+ ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+ ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions)
@@ -2692,23 +2918,23 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
// accessors -------------------------------------------------------
// required string name_part = 1;
- inline bool has_name_part() const;
- inline void clear_name_part();
+ bool has_name_part() const;
+ void clear_name_part();
static const int kNamePartFieldNumber = 1;
- inline const ::std::string& name_part() const;
- inline void set_name_part(const ::std::string& value);
- inline void set_name_part(const char* value);
- inline void set_name_part(const char* value, size_t size);
- inline ::std::string* mutable_name_part();
- inline ::std::string* release_name_part();
- inline void set_allocated_name_part(::std::string* name_part);
+ const ::std::string& name_part() const;
+ void set_name_part(const ::std::string& value);
+ void set_name_part(const char* value);
+ void set_name_part(const char* value, size_t size);
+ ::std::string* mutable_name_part();
+ ::std::string* release_name_part();
+ void set_allocated_name_part(::std::string* name_part);
// required bool is_extension = 2;
- inline bool has_is_extension() const;
- inline void clear_is_extension();
+ bool has_is_extension() const;
+ void clear_is_extension();
static const int kIsExtensionFieldNumber = 2;
- inline bool is_extension() const;
- inline void set_is_extension(bool value);
+ bool is_extension() const;
+ void set_is_extension(bool value);
// @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart)
private:
@@ -2801,73 +3027,73 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
// accessors -------------------------------------------------------
// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
- inline int name_size() const;
- inline void clear_name();
+ int name_size() const;
+ void clear_name();
static const int kNameFieldNumber = 2;
- inline const ::google::protobuf::UninterpretedOption_NamePart& name(int index) const;
- inline ::google::protobuf::UninterpretedOption_NamePart* mutable_name(int index);
- inline ::google::protobuf::UninterpretedOption_NamePart* add_name();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+ const ::google::protobuf::UninterpretedOption_NamePart& name(int index) const;
+ ::google::protobuf::UninterpretedOption_NamePart* mutable_name(int index);
+ ::google::protobuf::UninterpretedOption_NamePart* add_name();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
name() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
mutable_name();
// optional string identifier_value = 3;
- inline bool has_identifier_value() const;
- inline void clear_identifier_value();
+ bool has_identifier_value() const;
+ void clear_identifier_value();
static const int kIdentifierValueFieldNumber = 3;
- inline const ::std::string& identifier_value() const;
- inline void set_identifier_value(const ::std::string& value);
- inline void set_identifier_value(const char* value);
- inline void set_identifier_value(const char* value, size_t size);
- inline ::std::string* mutable_identifier_value();
- inline ::std::string* release_identifier_value();
- inline void set_allocated_identifier_value(::std::string* identifier_value);
+ const ::std::string& identifier_value() const;
+ void set_identifier_value(const ::std::string& value);
+ void set_identifier_value(const char* value);
+ void set_identifier_value(const char* value, size_t size);
+ ::std::string* mutable_identifier_value();
+ ::std::string* release_identifier_value();
+ void set_allocated_identifier_value(::std::string* identifier_value);
// optional uint64 positive_int_value = 4;
- inline bool has_positive_int_value() const;
- inline void clear_positive_int_value();
+ bool has_positive_int_value() const;
+ void clear_positive_int_value();
static const int kPositiveIntValueFieldNumber = 4;
- inline ::google::protobuf::uint64 positive_int_value() const;
- inline void set_positive_int_value(::google::protobuf::uint64 value);
+ ::google::protobuf::uint64 positive_int_value() const;
+ void set_positive_int_value(::google::protobuf::uint64 value);
// optional int64 negative_int_value = 5;
- inline bool has_negative_int_value() const;
- inline void clear_negative_int_value();
+ bool has_negative_int_value() const;
+ void clear_negative_int_value();
static const int kNegativeIntValueFieldNumber = 5;
- inline ::google::protobuf::int64 negative_int_value() const;
- inline void set_negative_int_value(::google::protobuf::int64 value);
+ ::google::protobuf::int64 negative_int_value() const;
+ void set_negative_int_value(::google::protobuf::int64 value);
// optional double double_value = 6;
- inline bool has_double_value() const;
- inline void clear_double_value();
+ bool has_double_value() const;
+ void clear_double_value();
static const int kDoubleValueFieldNumber = 6;
- inline double double_value() const;
- inline void set_double_value(double value);
+ double double_value() const;
+ void set_double_value(double value);
// optional bytes string_value = 7;
- inline bool has_string_value() const;
- inline void clear_string_value();
+ bool has_string_value() const;
+ void clear_string_value();
static const int kStringValueFieldNumber = 7;
- inline const ::std::string& string_value() const;
- inline void set_string_value(const ::std::string& value);
- inline void set_string_value(const char* value);
- inline void set_string_value(const void* value, size_t size);
- inline ::std::string* mutable_string_value();
- inline ::std::string* release_string_value();
- inline void set_allocated_string_value(::std::string* string_value);
+ const ::std::string& string_value() const;
+ void set_string_value(const ::std::string& value);
+ void set_string_value(const char* value);
+ void set_string_value(const void* value, size_t size);
+ ::std::string* mutable_string_value();
+ ::std::string* release_string_value();
+ void set_allocated_string_value(::std::string* string_value);
// optional string aggregate_value = 8;
- inline bool has_aggregate_value() const;
- inline void clear_aggregate_value();
+ bool has_aggregate_value() const;
+ void clear_aggregate_value();
static const int kAggregateValueFieldNumber = 8;
- inline const ::std::string& aggregate_value() const;
- inline void set_aggregate_value(const ::std::string& value);
- inline void set_aggregate_value(const char* value);
- inline void set_aggregate_value(const char* value, size_t size);
- inline ::std::string* mutable_aggregate_value();
- inline ::std::string* release_aggregate_value();
- inline void set_allocated_aggregate_value(::std::string* aggregate_value);
+ const ::std::string& aggregate_value() const;
+ void set_aggregate_value(const ::std::string& value);
+ void set_aggregate_value(const char* value);
+ void set_aggregate_value(const char* value, size_t size);
+ ::std::string* mutable_aggregate_value();
+ ::std::string* release_aggregate_value();
+ void set_allocated_aggregate_value(::std::string* aggregate_value);
// @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption)
private:
@@ -2968,52 +3194,68 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me
// accessors -------------------------------------------------------
// repeated int32 path = 1 [packed = true];
- inline int path_size() const;
- inline void clear_path();
+ int path_size() const;
+ void clear_path();
static const int kPathFieldNumber = 1;
- inline ::google::protobuf::int32 path(int index) const;
- inline void set_path(int index, ::google::protobuf::int32 value);
- inline void add_path(::google::protobuf::int32 value);
- inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+ ::google::protobuf::int32 path(int index) const;
+ void set_path(int index, ::google::protobuf::int32 value);
+ void add_path(::google::protobuf::int32 value);
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
path() const;
- inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
mutable_path();
// repeated int32 span = 2 [packed = true];
- inline int span_size() const;
- inline void clear_span();
+ int span_size() const;
+ void clear_span();
static const int kSpanFieldNumber = 2;
- inline ::google::protobuf::int32 span(int index) const;
- inline void set_span(int index, ::google::protobuf::int32 value);
- inline void add_span(::google::protobuf::int32 value);
- inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+ ::google::protobuf::int32 span(int index) const;
+ void set_span(int index, ::google::protobuf::int32 value);
+ void add_span(::google::protobuf::int32 value);
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
span() const;
- inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
mutable_span();
// optional string leading_comments = 3;
- inline bool has_leading_comments() const;
- inline void clear_leading_comments();
+ bool has_leading_comments() const;
+ void clear_leading_comments();
static const int kLeadingCommentsFieldNumber = 3;
- inline const ::std::string& leading_comments() const;
- inline void set_leading_comments(const ::std::string& value);
- inline void set_leading_comments(const char* value);
- inline void set_leading_comments(const char* value, size_t size);
- inline ::std::string* mutable_leading_comments();
- inline ::std::string* release_leading_comments();
- inline void set_allocated_leading_comments(::std::string* leading_comments);
+ const ::std::string& leading_comments() const;
+ void set_leading_comments(const ::std::string& value);
+ void set_leading_comments(const char* value);
+ void set_leading_comments(const char* value, size_t size);
+ ::std::string* mutable_leading_comments();
+ ::std::string* release_leading_comments();
+ void set_allocated_leading_comments(::std::string* leading_comments);
// optional string trailing_comments = 4;
- inline bool has_trailing_comments() const;
- inline void clear_trailing_comments();
+ bool has_trailing_comments() const;
+ void clear_trailing_comments();
static const int kTrailingCommentsFieldNumber = 4;
- inline const ::std::string& trailing_comments() const;
- inline void set_trailing_comments(const ::std::string& value);
- inline void set_trailing_comments(const char* value);
- inline void set_trailing_comments(const char* value, size_t size);
- inline ::std::string* mutable_trailing_comments();
- inline ::std::string* release_trailing_comments();
- inline void set_allocated_trailing_comments(::std::string* trailing_comments);
+ const ::std::string& trailing_comments() const;
+ void set_trailing_comments(const ::std::string& value);
+ void set_trailing_comments(const char* value);
+ void set_trailing_comments(const char* value, size_t size);
+ ::std::string* mutable_trailing_comments();
+ ::std::string* release_trailing_comments();
+ void set_allocated_trailing_comments(::std::string* trailing_comments);
+
+ // repeated string leading_detached_comments = 6;
+ int leading_detached_comments_size() const;
+ void clear_leading_detached_comments();
+ static const int kLeadingDetachedCommentsFieldNumber = 6;
+ const ::std::string& leading_detached_comments(int index) const;
+ ::std::string* mutable_leading_detached_comments(int index);
+ void set_leading_detached_comments(int index, const ::std::string& value);
+ void set_leading_detached_comments(int index, const char* value);
+ void set_leading_detached_comments(int index, const char* value, size_t size);
+ ::std::string* add_leading_detached_comments();
+ void add_leading_detached_comments(const ::std::string& value);
+ void add_leading_detached_comments(const char* value);
+ void add_leading_detached_comments(const char* value, size_t size);
+ const ::google::protobuf::RepeatedPtrField< ::std::string>& leading_detached_comments() const;
+ ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_leading_detached_comments();
// @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location)
private:
@@ -3031,6 +3273,7 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me
mutable int _span_cached_byte_size_;
::google::protobuf::internal::ArenaStringPtr leading_comments_;
::google::protobuf::internal::ArenaStringPtr trailing_comments_;
+ ::google::protobuf::RepeatedPtrField< ::std::string> leading_detached_comments_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
@@ -3107,15 +3350,15 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
// repeated .google.protobuf.SourceCodeInfo.Location location = 1;
- inline int location_size() const;
- inline void clear_location();
+ int location_size() const;
+ void clear_location();
static const int kLocationFieldNumber = 1;
- inline const ::google::protobuf::SourceCodeInfo_Location& location(int index) const;
- inline ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index);
- inline ::google::protobuf::SourceCodeInfo_Location* add_location();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+ const ::google::protobuf::SourceCodeInfo_Location& location(int index) const;
+ ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index);
+ ::google::protobuf::SourceCodeInfo_Location* add_location();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
location() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
mutable_location();
// @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo)
@@ -3137,6 +3380,7 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message {
// ===================================================================
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
// FileDescriptorSet
// repeated .google.protobuf.FileDescriptorProto file = 1;
@@ -3706,6 +3950,58 @@ inline void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 va
// -------------------------------------------------------------------
+// DescriptorProto_ReservedRange
+
+// optional int32 start = 1;
+inline bool DescriptorProto_ReservedRange::has_start() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void DescriptorProto_ReservedRange::set_has_start() {
+ _has_bits_[0] |= 0x00000001u;
+}
+inline void DescriptorProto_ReservedRange::clear_has_start() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+inline void DescriptorProto_ReservedRange::clear_start() {
+ start_ = 0;
+ clear_has_start();
+}
+inline ::google::protobuf::int32 DescriptorProto_ReservedRange::start() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.start)
+ return start_;
+}
+inline void DescriptorProto_ReservedRange::set_start(::google::protobuf::int32 value) {
+ set_has_start();
+ start_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.start)
+}
+
+// optional int32 end = 2;
+inline bool DescriptorProto_ReservedRange::has_end() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void DescriptorProto_ReservedRange::set_has_end() {
+ _has_bits_[0] |= 0x00000002u;
+}
+inline void DescriptorProto_ReservedRange::clear_has_end() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+inline void DescriptorProto_ReservedRange::clear_end() {
+ end_ = 0;
+ clear_has_end();
+}
+inline ::google::protobuf::int32 DescriptorProto_ReservedRange::end() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.end)
+ return end_;
+}
+inline void DescriptorProto_ReservedRange::set_end(::google::protobuf::int32 value) {
+ set_has_end();
+ end_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.end)
+}
+
+// -------------------------------------------------------------------
+
// DescriptorProto
// optional string name = 1;
@@ -3984,6 +4280,90 @@ inline void DescriptorProto::set_allocated_options(::google::protobuf::MessageOp
// @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options)
}
+// repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+inline int DescriptorProto::reserved_range_size() const {
+ return reserved_range_.size();
+}
+inline void DescriptorProto::clear_reserved_range() {
+ reserved_range_.Clear();
+}
+inline const ::google::protobuf::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_.Get(index);
+}
+inline ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::mutable_reserved_range(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_.Mutable(index);
+}
+inline ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() {
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
+DescriptorProto::reserved_range() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
+DescriptorProto::mutable_reserved_range() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_range)
+ return &reserved_range_;
+}
+
+// repeated string reserved_name = 10;
+inline int DescriptorProto::reserved_name_size() const {
+ return reserved_name_.size();
+}
+inline void DescriptorProto::clear_reserved_name() {
+ reserved_name_.Clear();
+}
+inline const ::std::string& DescriptorProto::reserved_name(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_name)
+ return reserved_name_.Get(index);
+}
+inline ::std::string* DescriptorProto::mutable_reserved_name(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_name)
+ return reserved_name_.Mutable(index);
+}
+inline void DescriptorProto::set_reserved_name(int index, const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name)
+ reserved_name_.Mutable(index)->assign(value);
+}
+inline void DescriptorProto::set_reserved_name(int index, const char* value) {
+ reserved_name_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.reserved_name)
+}
+inline void DescriptorProto::set_reserved_name(int index, const char* value, size_t size) {
+ reserved_name_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.reserved_name)
+}
+inline ::std::string* DescriptorProto::add_reserved_name() {
+ return reserved_name_.Add();
+}
+inline void DescriptorProto::add_reserved_name(const ::std::string& value) {
+ reserved_name_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name)
+}
+inline void DescriptorProto::add_reserved_name(const char* value) {
+ reserved_name_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.DescriptorProto.reserved_name)
+}
+inline void DescriptorProto::add_reserved_name(const char* value, size_t size) {
+ reserved_name_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.DescriptorProto.reserved_name)
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+DescriptorProto::reserved_name() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_name)
+ return reserved_name_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+DescriptorProto::mutable_reserved_name() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_name)
+ return &reserved_name_;
+}
+
// -------------------------------------------------------------------
// FieldDescriptorProto
@@ -5416,6 +5796,136 @@ inline void FileOptions::set_cc_enable_arenas(bool value) {
// @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_enable_arenas)
}
+// optional string objc_class_prefix = 36;
+inline bool FileOptions::has_objc_class_prefix() const {
+ return (_has_bits_[0] & 0x00001000u) != 0;
+}
+inline void FileOptions::set_has_objc_class_prefix() {
+ _has_bits_[0] |= 0x00001000u;
+}
+inline void FileOptions::clear_has_objc_class_prefix() {
+ _has_bits_[0] &= ~0x00001000u;
+}
+inline void FileOptions::clear_objc_class_prefix() {
+ objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_objc_class_prefix();
+}
+inline const ::std::string& FileOptions::objc_class_prefix() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix)
+ return objc_class_prefix_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_objc_class_prefix(const ::std::string& value) {
+ set_has_objc_class_prefix();
+ objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix)
+}
+inline void FileOptions::set_objc_class_prefix(const char* value) {
+ set_has_objc_class_prefix();
+ objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix)
+}
+inline void FileOptions::set_objc_class_prefix(const char* value, size_t size) {
+ set_has_objc_class_prefix();
+ objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix)
+}
+inline ::std::string* FileOptions::mutable_objc_class_prefix() {
+ set_has_objc_class_prefix();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix)
+ return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FileOptions::release_objc_class_prefix() {
+ clear_has_objc_class_prefix();
+ return objc_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_allocated_objc_class_prefix(::std::string* objc_class_prefix) {
+ if (objc_class_prefix != NULL) {
+ set_has_objc_class_prefix();
+ } else {
+ clear_has_objc_class_prefix();
+ }
+ objc_class_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), objc_class_prefix);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix)
+}
+
+// optional string csharp_namespace = 37;
+inline bool FileOptions::has_csharp_namespace() const {
+ return (_has_bits_[0] & 0x00002000u) != 0;
+}
+inline void FileOptions::set_has_csharp_namespace() {
+ _has_bits_[0] |= 0x00002000u;
+}
+inline void FileOptions::clear_has_csharp_namespace() {
+ _has_bits_[0] &= ~0x00002000u;
+}
+inline void FileOptions::clear_csharp_namespace() {
+ csharp_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_csharp_namespace();
+}
+inline const ::std::string& FileOptions::csharp_namespace() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_namespace)
+ return csharp_namespace_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_csharp_namespace(const ::std::string& value) {
+ set_has_csharp_namespace();
+ csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_namespace)
+}
+inline void FileOptions::set_csharp_namespace(const char* value) {
+ set_has_csharp_namespace();
+ csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_namespace)
+}
+inline void FileOptions::set_csharp_namespace(const char* value, size_t size) {
+ set_has_csharp_namespace();
+ csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_namespace)
+}
+inline ::std::string* FileOptions::mutable_csharp_namespace() {
+ set_has_csharp_namespace();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_namespace)
+ return csharp_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FileOptions::release_csharp_namespace() {
+ clear_has_csharp_namespace();
+ return csharp_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_allocated_csharp_namespace(::std::string* csharp_namespace) {
+ if (csharp_namespace != NULL) {
+ set_has_csharp_namespace();
+ } else {
+ clear_has_csharp_namespace();
+ }
+ csharp_namespace_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), csharp_namespace);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace)
+}
+
+// optional bool javanano_use_deprecated_package = 38;
+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();
@@ -5629,15 +6139,40 @@ inline void FieldOptions::set_packed(bool value) {
// @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed)
}
+// optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+inline bool FieldOptions::has_jstype() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void FieldOptions::set_has_jstype() {
+ _has_bits_[0] |= 0x00000004u;
+}
+inline void FieldOptions::clear_has_jstype() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+inline void FieldOptions::clear_jstype() {
+ jstype_ = 0;
+ clear_has_jstype();
+}
+inline ::google::protobuf::FieldOptions_JSType FieldOptions::jstype() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.jstype)
+ return static_cast< ::google::protobuf::FieldOptions_JSType >(jstype_);
+}
+inline void FieldOptions::set_jstype(::google::protobuf::FieldOptions_JSType value) {
+ assert(::google::protobuf::FieldOptions_JSType_IsValid(value));
+ set_has_jstype();
+ jstype_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.jstype)
+}
+
// optional bool lazy = 5 [default = false];
inline bool FieldOptions::has_lazy() const {
- return (_has_bits_[0] & 0x00000004u) != 0;
+ return (_has_bits_[0] & 0x00000008u) != 0;
}
inline void FieldOptions::set_has_lazy() {
- _has_bits_[0] |= 0x00000004u;
+ _has_bits_[0] |= 0x00000008u;
}
inline void FieldOptions::clear_has_lazy() {
- _has_bits_[0] &= ~0x00000004u;
+ _has_bits_[0] &= ~0x00000008u;
}
inline void FieldOptions::clear_lazy() {
lazy_ = false;
@@ -5655,13 +6190,13 @@ inline void FieldOptions::set_lazy(bool value) {
// optional bool deprecated = 3 [default = false];
inline bool FieldOptions::has_deprecated() const {
- return (_has_bits_[0] & 0x00000008u) != 0;
+ return (_has_bits_[0] & 0x00000010u) != 0;
}
inline void FieldOptions::set_has_deprecated() {
- _has_bits_[0] |= 0x00000008u;
+ _has_bits_[0] |= 0x00000010u;
}
inline void FieldOptions::clear_has_deprecated() {
- _has_bits_[0] &= ~0x00000008u;
+ _has_bits_[0] &= ~0x00000010u;
}
inline void FieldOptions::clear_deprecated() {
deprecated_ = false;
@@ -5679,13 +6214,13 @@ inline void FieldOptions::set_deprecated(bool value) {
// optional bool weak = 10 [default = false];
inline bool FieldOptions::has_weak() const {
- return (_has_bits_[0] & 0x00000010u) != 0;
+ return (_has_bits_[0] & 0x00000020u) != 0;
}
inline void FieldOptions::set_has_weak() {
- _has_bits_[0] |= 0x00000010u;
+ _has_bits_[0] |= 0x00000020u;
}
inline void FieldOptions::clear_has_weak() {
- _has_bits_[0] &= ~0x00000010u;
+ _has_bits_[0] &= ~0x00000020u;
}
inline void FieldOptions::clear_weak() {
weak_ = false;
@@ -6503,6 +7038,60 @@ inline void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::stri
// @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments)
}
+// repeated string leading_detached_comments = 6;
+inline int SourceCodeInfo_Location::leading_detached_comments_size() const {
+ return leading_detached_comments_.size();
+}
+inline void SourceCodeInfo_Location::clear_leading_detached_comments() {
+ leading_detached_comments_.Clear();
+}
+inline const ::std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ return leading_detached_comments_.Get(index);
+}
+inline ::std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ return leading_detached_comments_.Mutable(index);
+}
+inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ leading_detached_comments_.Mutable(index)->assign(value);
+}
+inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) {
+ leading_detached_comments_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, size_t size) {
+ leading_detached_comments_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline ::std::string* SourceCodeInfo_Location::add_leading_detached_comments() {
+ return leading_detached_comments_.Add();
+}
+inline void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) {
+ leading_detached_comments_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) {
+ leading_detached_comments_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, size_t size) {
+ leading_detached_comments_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+SourceCodeInfo_Location::leading_detached_comments() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ return leading_detached_comments_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+SourceCodeInfo_Location::mutable_leading_detached_comments() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ return &leading_detached_comments_;
+}
+
// -------------------------------------------------------------------
// SourceCodeInfo
@@ -6537,6 +7126,49 @@ SourceCodeInfo::mutable_location() {
return &location_;
}
+#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
// @@protoc_insertion_point(namespace_scope)
@@ -6567,6 +7199,11 @@ template <>
inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions_CType>() {
return ::google::protobuf::FieldOptions_CType_descriptor();
}
+template <> struct is_proto_enum< ::google::protobuf::FieldOptions_JSType> : ::google::protobuf::internal::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions_JSType>() {
+ return ::google::protobuf::FieldOptions_JSType_descriptor();
+}
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index e17c0cc8..9d3dd8fb 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -40,8 +40,12 @@
syntax = "proto2";
package google.protobuf;
+option go_package = "descriptor";
option java_package = "com.google.protobuf";
+option javanano_use_deprecated_package = true;
option java_outer_classname = "DescriptorProtos";
+option csharp_namespace = "Google.Protobuf.Reflection";
+option objc_class_prefix = "GPB";
// descriptor.proto must be optimized for speed because reflection-based
// algorithms don't work during bootstrapping.
@@ -104,6 +108,18 @@ message DescriptorProto {
repeated OneofDescriptorProto oneof_decl = 8;
optional MessageOptions options = 7;
+
+ // Range of reserved tag numbers. Reserved tag numbers may not be used by
+ // fields or extension ranges in the same message. Reserved ranges may
+ // not overlap.
+ message ReservedRange {
+ optional int32 start = 1; // Inclusive.
+ optional int32 end = 2; // Exclusive.
+ }
+ repeated ReservedRange reserved_range = 9;
+ // Reserved field names, which may not be used by fields in the same message.
+ // A given name may only be reserved once.
+ repeated string reserved_name = 10;
}
// Describes a field within a message.
@@ -172,9 +188,7 @@ message FieldDescriptorProto {
optional string default_value = 7;
// If set, gives the index of a oneof in the containing type's oneof_decl
- // list. This field is a member of that oneof. Extensions of a oneof should
- // not set this since the oneof to which they belong will be inferred based
- // on the extension range containing the extension's field number.
+ // list. This field is a member of that oneof.
optional int32 oneof_index = 9;
optional FieldOptions options = 8;
@@ -251,11 +265,11 @@ message MethodDescriptorProto {
// * For options which will be published and used publicly by multiple
// independent entities, e-mail protobuf-global-extension-registry@google.com
// to reserve extension numbers. Simply provide your project name (e.g.
-// Object-C plugin) and your porject website (if available) -- there's no need
-// to explain how you intend to use them. Usually you only need one extension
-// number. You can declare multiple options with only one extension number by
-// putting them in a sub-message. See the Custom Options section of the docs
-// for examples:
+// Objective-C plugin) and your project website (if available) -- there's no
+// need to explain how you intend to use them. Usually you only need one
+// extension number. You can declare multiple options with only one extension
+// number by putting them in a sub-message. See the Custom Options section of
+// the docs for examples:
// https://developers.google.com/protocol-buffers/docs/proto#options
// If this turns out to be popular, a web service will be set up
// to automatically assign option numbers.
@@ -344,12 +358,22 @@ message FileOptions {
// least, this is a formalization for deprecating files.
optional bool deprecated = 23 [default=false];
-
// Enables the use of arenas for the proto messages in this file. This applies
// only to generated classes for C++.
optional bool cc_enable_arenas = 31 [default=false];
+ // Sets the objective c class prefix which is prepended to all objective c
+ // generated classes from this .proto. There is no default.
+ optional string objc_class_prefix = 36;
+
+ // 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;
+
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
@@ -436,10 +460,31 @@ message FieldOptions {
// The packed option can be enabled for repeated primitive fields to enable
// a more efficient representation on the wire. Rather than repeatedly
// writing the tag and type for each element, the entire array is encoded as
- // a single length-delimited blob.
+ // a single length-delimited blob. In proto3, only explicit setting it to
+ // false will avoid using packed encoding.
optional bool packed = 2;
+ // The jstype option determines the JavaScript type used for values of the
+ // field. The option is permitted only for 64 bit integral and fixed types
+ // (int64, uint64, sint64, fixed64, sfixed64). By default these types are
+ // represented as JavaScript strings. This avoids loss of precision that can
+ // happen when a large value is converted to a floating point JavaScript
+ // numbers. Specifying JS_NUMBER for the jstype causes the generated
+ // JavaScript code to use the JavaScript "number" type instead of strings.
+ // This option is an enum to permit additional types to be added,
+ // e.g. goog.math.Integer.
+ optional JSType jstype = 6 [default = JS_NORMAL];
+ enum JSType {
+ // Use the default type.
+ JS_NORMAL = 0;
+
+ // Use JavaScript strings.
+ JS_STRING = 1;
+
+ // Use JavaScript numbers.
+ JS_NUMBER = 2;
+ }
// Should this field be parsed lazily? Lazy applies only to message-type
// fields. It means that when the outer message is initially parsed, the
@@ -480,8 +525,6 @@ message FieldOptions {
// For Google-internal migration only. Do not use.
optional bool weak = 10 [default=false];
-
-
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
@@ -681,6 +724,11 @@ message SourceCodeInfo {
// A series of line comments appearing on consecutive lines, with no other
// tokens appearing on those lines, will be treated as a single comment.
//
+ // leading_detached_comments will keep paragraphs of comments that appear
+ // before (but not connected to) the current element. Each paragraph,
+ // separated by empty lines, will be one comment element in the repeated
+ // field.
+ //
// Only the comment content is provided; comment markers (e.g. //) are
// stripped out. For block comments, leading whitespace and an asterisk
// will be stripped from the beginning of each line other than the first.
@@ -701,6 +749,12 @@ message SourceCodeInfo {
// // Another line attached to qux.
// optional double qux = 4;
//
+ // // Detached comment for corge. This is not leading or trailing comments
+ // // to qux or corge because there are blank lines separating it from
+ // // both.
+ //
+ // // Detached comment for corge paragraph 2.
+ //
// optional string corge = 5;
// /* Block comment attached
// * to corge. Leading asterisks
@@ -708,7 +762,10 @@ message SourceCodeInfo {
// /* Block comment attached to
// * grault. */
// optional int32 grault = 6;
+ //
+ // // ignored detached comments.
optional string leading_comments = 3;
optional string trailing_comments = 4;
+ repeated string leading_detached_comments = 6;
}
}
diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc
index d024eab1..2117c020 100644
--- a/src/google/protobuf/descriptor_database.cc
+++ b/src/google/protobuf/descriptor_database.cc
@@ -153,10 +153,10 @@ bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddExtension(
if (!field.extendee().empty() && field.extendee()[0] == '.') {
// The extension is fully-qualified. We can use it as a lookup key in
// the by_symbol_ table.
- if (!InsertIfNotPresent(&by_extension_,
- make_pair(field.extendee().substr(1),
- field.number()),
- value)) {
+ if (!InsertIfNotPresent(
+ &by_extension_,
+ std::make_pair(field.extendee().substr(1), field.number()),
+ value)) {
GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: "
"extend " << field.extendee() << " { "
<< field.name() << " = " << field.number() << " }";
@@ -189,17 +189,16 @@ template <typename Value>
Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindExtension(
const string& containing_type,
int field_number) {
- return FindWithDefault(by_extension_,
- make_pair(containing_type, field_number),
- Value());
+ return FindWithDefault(
+ by_extension_, std::make_pair(containing_type, field_number), Value());
}
template <typename Value>
bool SimpleDescriptorDatabase::DescriptorIndex<Value>::FindAllExtensionNumbers(
const string& containing_type,
vector<int>* output) {
- typename map<pair<string, int>, Value >::const_iterator it =
- by_extension_.lower_bound(make_pair(containing_type, 0));
+ typename map<pair<string, int>, Value>::const_iterator it =
+ by_extension_.lower_bound(std::make_pair(containing_type, 0));
bool success = false;
for (; it != by_extension_.end() && it->first.first == containing_type;
@@ -310,7 +309,7 @@ bool EncodedDescriptorDatabase::Add(
const void* encoded_file_descriptor, int size) {
FileDescriptorProto file;
if (file.ParseFromArray(encoded_file_descriptor, size)) {
- return index_.AddFile(file, make_pair(encoded_file_descriptor, size));
+ return index_.AddFile(file, std::make_pair(encoded_file_descriptor, size));
} else {
GOOGLE_LOG(ERROR) << "Invalid file descriptor data passed to "
"EncodedDescriptorDatabase::Add().";
@@ -525,15 +524,16 @@ bool MergedDescriptorDatabase::FindAllExtensionNumbers(
for (int i = 0; i < sources_.size(); i++) {
if (sources_[i]->FindAllExtensionNumbers(extendee_type, &results)) {
- copy(results.begin(), results.end(),
- insert_iterator<set<int> >(merged_results, merged_results.begin()));
+ std::copy(
+ results.begin(), results.end(),
+ insert_iterator<set<int> >(merged_results, merged_results.begin()));
success = true;
}
results.clear();
}
- copy(merged_results.begin(), merged_results.end(),
- insert_iterator<vector<int> >(*output, output->end()));
+ std::copy(merged_results.begin(), merged_results.end(),
+ insert_iterator<vector<int> >(*output, output->end()));
return success;
}
diff --git a/src/google/protobuf/descriptor_database.h b/src/google/protobuf/descriptor_database.h
index 934e4022..86002d56 100644
--- a/src/google/protobuf/descriptor_database.h
+++ b/src/google/protobuf/descriptor_database.h
@@ -312,7 +312,7 @@ class LIBPROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase {
// A DescriptorDatabase that fetches files from a given pool.
class LIBPROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase {
public:
- DescriptorPoolDatabase(const DescriptorPool& pool);
+ explicit DescriptorPoolDatabase(const DescriptorPool& pool);
~DescriptorPoolDatabase();
// implements DescriptorDatabase -----------------------------------
@@ -341,7 +341,7 @@ class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase {
// Merge more than two databases. The sources remain property of the caller.
// The vector may be deleted after the constructor returns but the
// DescriptorDatabases need to stick around.
- MergedDescriptorDatabase(const vector<DescriptorDatabase*>& sources);
+ explicit MergedDescriptorDatabase(const vector<DescriptorDatabase*>& sources);
~MergedDescriptorDatabase();
// implements DescriptorDatabase -----------------------------------
diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc
index 6642d71b..1c03c443 100644
--- a/src/google/protobuf/descriptor_database_unittest.cc
+++ b/src/google/protobuf/descriptor_database_unittest.cc
@@ -408,7 +408,7 @@ TEST_P(DescriptorDatabaseTest, FindAllExtensionNumbers) {
vector<int> numbers;
EXPECT_TRUE(database_->FindAllExtensionNumbers("Foo", &numbers));
ASSERT_EQ(2, numbers.size());
- sort(numbers.begin(), numbers.end());
+ std::sort(numbers.begin(), numbers.end());
EXPECT_EQ(5, numbers[0]);
EXPECT_EQ(32, numbers[1]);
}
@@ -722,7 +722,7 @@ TEST_F(MergedDescriptorDatabaseTest, FindAllExtensionNumbers) {
vector<int> numbers;
EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Baz", &numbers));
ASSERT_EQ(2, numbers.size());
- sort(numbers.begin(), numbers.end());
+ std::sort(numbers.begin(), numbers.end());
EXPECT_EQ(12, numbers[0]);
EXPECT_EQ(13, numbers[1]);
}
@@ -731,7 +731,7 @@ TEST_F(MergedDescriptorDatabaseTest, FindAllExtensionNumbers) {
vector<int> numbers;
EXPECT_TRUE(reverse_merged_.FindAllExtensionNumbers("Baz", &numbers));
ASSERT_EQ(2, numbers.size());
- sort(numbers.begin(), numbers.end());
+ std::sort(numbers.begin(), numbers.end());
EXPECT_EQ(12, numbers[0]);
EXPECT_EQ(13, numbers[1]);
}
diff --git a/src/google/protobuf/descriptor_pb2_test.py b/src/google/protobuf/descriptor_pb2_test.py
deleted file mode 100644
index c5a8d8a2..00000000
--- a/src/google/protobuf/descriptor_pb2_test.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#! /usr/bin/python
-#
-# Protocol Buffers - Google's data interchange format
-# Copyright 2008 Google Inc. All rights reserved.
-# https://developers.google.com/protocol-buffers/
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# Verify that prebuild and checkedin version of descriptor_pb2.py is up to date.
-
-from google3.pyglib import resources
-from google.apputils import basetest
-
-_DESC = 'google3/net/proto2/proto/descriptor_pb2.'
-_OLD = _DESC + 'py-prebuilt'
-_NEW = _DESC + 'compiled'
-
-
-class PregeneratedFileChanged(basetest.TestCase):
-
- def testSameText(self):
- generated = resources.GetResource(_NEW)
- checkedin = resources.GetResource(_OLD)
- self.assertMultiLineEqual(
- generated, checkedin, 'It seems that protoc _pb2 generator changed. '
- 'Please run google/protobuf/generate_descriptor_proto.sh to '
- 'regnerate a new version of %s and add it to your CL' % _OLD)
-
-if __name__ == '__main__':
- basetest.main()
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index 2ceb41e5..760df097 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -139,6 +139,14 @@ DescriptorProto::ExtensionRange* AddExtensionRange(DescriptorProto* parent,
return result;
}
+DescriptorProto::ReservedRange* AddReservedRange(DescriptorProto* parent,
+ int start, int end) {
+ DescriptorProto::ReservedRange* result = parent->add_reserved_range();
+ result->set_start(start);
+ result->set_end(end);
+ return result;
+}
+
EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto,
const string& name, int number) {
EnumValueDescriptorProto* result = enum_proto->add_value();
@@ -1720,6 +1728,84 @@ TEST_F(ExtensionDescriptorTest, DuplicateFieldNumber) {
// ===================================================================
+// Test reserved fields.
+class ReservedDescriptorTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ // Build descriptors for the following definitions:
+ //
+ // message Foo {
+ // reserved 2, 9 to 11, 15;
+ // reserved "foo", "bar";
+ // }
+
+ FileDescriptorProto foo_file;
+ foo_file.set_name("foo.proto");
+
+ DescriptorProto* foo = AddMessage(&foo_file, "Foo");
+ AddReservedRange(foo, 2, 3);
+ AddReservedRange(foo, 9, 12);
+ AddReservedRange(foo, 15, 16);
+
+ foo->add_reserved_name("foo");
+ foo->add_reserved_name("bar");
+
+ // Build the descriptors and get the pointers.
+ foo_file_ = pool_.BuildFile(foo_file);
+ ASSERT_TRUE(foo_file_ != NULL);
+
+ ASSERT_EQ(1, foo_file_->message_type_count());
+ foo_ = foo_file_->message_type(0);
+ }
+
+ DescriptorPool pool_;
+ const FileDescriptor* foo_file_;
+ const Descriptor* foo_;
+};
+
+TEST_F(ReservedDescriptorTest, ReservedRanges) {
+ ASSERT_EQ(3, foo_->reserved_range_count());
+
+ EXPECT_EQ(2, foo_->reserved_range(0)->start);
+ EXPECT_EQ(3, foo_->reserved_range(0)->end);
+
+ EXPECT_EQ(9, foo_->reserved_range(1)->start);
+ EXPECT_EQ(12, foo_->reserved_range(1)->end);
+
+ EXPECT_EQ(15, foo_->reserved_range(2)->start);
+ EXPECT_EQ(16, foo_->reserved_range(2)->end);
+};
+
+TEST_F(ReservedDescriptorTest, IsReservedNumber) {
+ EXPECT_FALSE(foo_->IsReservedNumber(1));
+ EXPECT_TRUE (foo_->IsReservedNumber(2));
+ EXPECT_FALSE(foo_->IsReservedNumber(3));
+ EXPECT_FALSE(foo_->IsReservedNumber(8));
+ EXPECT_TRUE (foo_->IsReservedNumber(9));
+ EXPECT_TRUE (foo_->IsReservedNumber(10));
+ EXPECT_TRUE (foo_->IsReservedNumber(11));
+ EXPECT_FALSE(foo_->IsReservedNumber(12));
+ EXPECT_FALSE(foo_->IsReservedNumber(13));
+ EXPECT_FALSE(foo_->IsReservedNumber(14));
+ EXPECT_TRUE (foo_->IsReservedNumber(15));
+ EXPECT_FALSE(foo_->IsReservedNumber(16));
+};
+
+TEST_F(ReservedDescriptorTest, ReservedNames) {
+ ASSERT_EQ(2, foo_->reserved_name_count());
+
+ EXPECT_EQ("foo", foo_->reserved_name(0));
+ EXPECT_EQ("bar", foo_->reserved_name(1));
+};
+
+TEST_F(ReservedDescriptorTest, IsReservedName) {
+ EXPECT_TRUE (foo_->IsReservedName("foo"));
+ EXPECT_TRUE (foo_->IsReservedName("bar"));
+ EXPECT_FALSE(foo_->IsReservedName("baz"));
+};
+
+// ===================================================================
+
class MiscTest : public testing::Test {
protected:
// Function which makes a field descriptor of the given type.
@@ -2997,10 +3083,10 @@ class ValidationErrorTest : public testing::Test {
protected:
// Parse file_text as a FileDescriptorProto in text format and add it
// to the DescriptorPool. Expect no errors.
- void BuildFile(const string& file_text) {
+ const FileDescriptor* BuildFile(const string& file_text) {
FileDescriptorProto file_proto;
- ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
- ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL);
+ EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
+ return GOOGLE_CHECK_NOTNULL(pool_.BuildFile(file_proto));
}
// Parse file_text as a FileDescriptorProto in text format and add it
@@ -3251,6 +3337,102 @@ TEST_F(ValidationErrorTest, OverlappingExtensionRanges) {
"already-defined range 20 to 29.\n");
}
+TEST_F(ValidationErrorTest, ReservedFieldError) {
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ " reserved_range { start: 10 end: 20 }"
+ "}",
+
+ "foo.proto: Foo.foo: NUMBER: Field \"foo\" uses reserved number 15.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedExtensionRangeError) {
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " extension_range { start: 10 end: 20 }"
+ " reserved_range { start: 5 end: 15 }"
+ "}",
+
+ "foo.proto: Foo: NUMBER: Extension range 10 to 19"
+ " overlaps with reserved range 5 to 14.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedExtensionRangeAdjacent) {
+ BuildFile(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " extension_range { start: 10 end: 20 }"
+ " reserved_range { start: 5 end: 10 }"
+ "}");
+}
+
+TEST_F(ValidationErrorTest, ReservedRangeOverlap) {
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " reserved_range { start: 10 end: 20 }"
+ " reserved_range { start: 5 end: 15 }"
+ "}",
+
+ "foo.proto: Foo: NUMBER: Reserved range 5 to 14"
+ " overlaps with already-defined range 10 to 19.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedNameError) {
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ " field { name: \"bar\" number: 16 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ " field { name: \"baz\" number: 17 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ " reserved_name: \"foo\""
+ " reserved_name: \"bar\""
+ "}",
+
+ "foo.proto: Foo.foo: NAME: Field name \"foo\" is reserved.\n"
+ "foo.proto: Foo.bar: NAME: Field name \"bar\" is reserved.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedNameRedundant) {
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " reserved_name: \"foo\""
+ " reserved_name: \"foo\""
+ "}",
+
+ "foo.proto: foo: NAME: Field name \"foo\" is reserved multiple times.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedFieldsDebugString) {
+ const FileDescriptor* file = BuildFile(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " reserved_name: \"foo\""
+ " reserved_name: \"bar\""
+ " reserved_range { start: 5 end: 6 }"
+ " reserved_range { start: 10 end: 20 }"
+ "}");
+
+ ASSERT_EQ(
+ "syntax = \"proto2\";\n\n"
+ "message Foo {\n"
+ " reserved 5, 10 to 19;\n"
+ " reserved \"foo\", \"bar\";\n"
+ "}\n\n",
+ file->DebugString());
+}
+
TEST_F(ValidationErrorTest, InvalidDefaults) {
BuildFileWithErrors(
"name: \"foo.proto\" "
@@ -3399,6 +3581,48 @@ TEST_F(ValidationErrorTest, FieldOneofIndexNegative) {
"range for type \"Foo\".\n");
}
+TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) {
+ // Fields belonging to the same oneof must be defined consecutively.
+ BuildFileWithWarnings(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 0 }"
+ " field { name:\"bar\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ " field { name:\"foo2\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 0 }"
+ " oneof_decl { name:\"foos\" }"
+ "}",
+
+ "foo.proto: Foo.bar: OTHER: Fields in the same oneof must be defined "
+ "consecutively. \"bar\" cannot be defined before the completion of the "
+ "\"foos\" oneof definition.\n");
+
+ // Prevent interleaved fields, which belong to different oneofs.
+ BuildFileWithWarnings(
+ "name: \"foo2.proto\" "
+ "message_type {"
+ " name: \"Foo2\""
+ " field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 0 }"
+ " field { name:\"bar1\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 1 }"
+ " field { name:\"foo2\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 0 }"
+ " field { name:\"bar2\" number: 4 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 1 }"
+ " oneof_decl { name:\"foos\" }"
+ " oneof_decl { name:\"bars\" }"
+ "}",
+ "foo2.proto: Foo2.bar1: OTHER: Fields in the same oneof must be defined "
+ "consecutively. \"bar1\" cannot be defined before the completion of the "
+ "\"foos\" oneof definition.\n"
+ "foo2.proto: Foo2.foo2: OTHER: Fields in the same oneof must be defined "
+ "consecutively. \"foo2\" cannot be defined before the completion of the "
+ "\"bars\" oneof definition.\n");
+}
+
TEST_F(ValidationErrorTest, FieldNumberConflict) {
BuildFileWithErrors(
"name: \"foo.proto\" "
@@ -5293,6 +5517,22 @@ TEST_F(ValidationErrorTest, ValidateProto3LiteRuntime) {
"in proto3.\n");
}
+TEST_F(ValidationErrorTest, ValidateProto3Group) {
+ BuildFileWithErrors(
+ "name: 'foo.proto' "
+ "syntax: 'proto3' "
+ "message_type { "
+ " name: 'Foo' "
+ " nested_type { "
+ " name: 'FooGroup' "
+ " } "
+ " field { name:'foo_group' number: 1 label:LABEL_OPTIONAL "
+ " type: TYPE_GROUP type_name:'FooGroup' } "
+ "}",
+ "foo.proto: Foo.foo_group: TYPE: Groups are not supported in proto3 "
+ "syntax.\n");
+}
+
TEST_F(ValidationErrorTest, ValidateProto3EnumFromProto2) {
// Define an enum in a proto2 file.
@@ -6104,9 +6344,9 @@ TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) {
file_desc->CopySourceCodeInfoTo(&file_desc_proto);
const SourceCodeInfo& info = file_desc_proto.source_code_info();
- ASSERT_EQ(3, info.location_size());
+ ASSERT_EQ(4, info.location_size());
// Get the Foo message location
- const SourceCodeInfo_Location& foo_location = info.location(1);
+ const SourceCodeInfo_Location& foo_location = info.location(2);
ASSERT_EQ(2, foo_location.path_size());
EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0));
EXPECT_EQ(0, foo_location.path(1)); // Foo is the first message defined
diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc
new file mode 100644
index 00000000..2e22ccb1
--- /dev/null
+++ b/src/google/protobuf/duration.pb.cc
@@ -0,0 +1,407 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/duration.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "google/protobuf/duration.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* Duration_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ Duration_reflection_ = NULL;
+
+} // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fduration_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto();
+ const ::google::protobuf::FileDescriptor* file =
+ ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+ "google/protobuf/duration.proto");
+ GOOGLE_CHECK(file != NULL);
+ Duration_descriptor_ = file->message_type(0);
+ static const int Duration_offsets_[2] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Duration, seconds_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Duration, nanos_),
+ };
+ Duration_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ Duration_descriptor_,
+ Duration::default_instance_,
+ Duration_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(Duration),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Duration, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Duration, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+ ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+ &protobuf_AssignDesc_google_2fprotobuf_2fduration_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ Duration_descriptor_, &Duration::default_instance());
+}
+
+} // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fduration_2eproto() {
+ delete Duration::default_instance_;
+ delete Duration_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto() {
+ static bool already_here = false;
+ if (already_here) return;
+ already_here = true;
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ ::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);
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+ "google/protobuf/duration.proto", &protobuf_RegisterTypes);
+ Duration::default_instance_ = new Duration();
+ Duration::default_instance_->InitAsDefaultInstance();
+ ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fduration_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fduration_2eproto {
+ StaticDescriptorInitializer_google_2fprotobuf_2fduration_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto();
+ }
+} static_descriptor_initializer_google_2fprotobuf_2fduration_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+ GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+} // namespace
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int Duration::kSecondsFieldNumber;
+const int Duration::kNanosFieldNumber;
+#endif // !_MSC_VER
+
+Duration::Duration()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.Duration)
+}
+
+void Duration::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+Duration::Duration(const Duration& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.Duration)
+}
+
+void Duration::SharedCtor() {
+ _is_default_instance_ = false;
+ _cached_size_ = 0;
+ seconds_ = GOOGLE_LONGLONG(0);
+ nanos_ = 0;
+}
+
+Duration::~Duration() {
+ // @@protoc_insertion_point(destructor:google.protobuf.Duration)
+ SharedDtor();
+}
+
+void Duration::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void Duration::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Duration::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Duration_descriptor_;
+}
+
+const Duration& Duration::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto();
+ return *default_instance_;
+}
+
+Duration* Duration::default_instance_ = NULL;
+
+Duration* Duration::New(::google::protobuf::Arena* arena) const {
+ Duration* n = new Duration;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void Duration::Clear() {
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<Duration*>(16)->f)
+
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+ ZR_(seconds_, nanos_);
+
+#undef ZR_HELPER_
+#undef ZR_
+
+}
+
+bool Duration::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.Duration)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional int64 seconds = 1;
+ case 1: {
+ if (tag == 8) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
+ input, &seconds_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(16)) goto parse_nanos;
+ break;
+ }
+
+ // optional int32 nanos = 2;
+ case 2: {
+ if (tag == 16) {
+ parse_nanos:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &nanos_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.Duration)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.Duration)
+ return false;
+#undef DO_
+}
+
+void Duration::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.Duration)
+ // optional int64 seconds = 1;
+ if (this->seconds() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt64(1, this->seconds(), output);
+ }
+
+ // optional int32 nanos = 2;
+ if (this->nanos() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->nanos(), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.Duration)
+}
+
+::google::protobuf::uint8* Duration::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Duration)
+ // optional int64 seconds = 1;
+ if (this->seconds() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(1, this->seconds(), target);
+ }
+
+ // optional int32 nanos = 2;
+ if (this->nanos() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->nanos(), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Duration)
+ return target;
+}
+
+int Duration::ByteSize() const {
+ int total_size = 0;
+
+ // optional int64 seconds = 1;
+ if (this->seconds() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int64Size(
+ this->seconds());
+ }
+
+ // optional int32 nanos = 2;
+ if (this->nanos() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->nanos());
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void Duration::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const Duration* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Duration>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void Duration::MergeFrom(const Duration& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from.seconds() != 0) {
+ set_seconds(from.seconds());
+ }
+ if (from.nanos() != 0) {
+ set_nanos(from.nanos());
+ }
+}
+
+void Duration::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void Duration::CopyFrom(const Duration& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Duration::IsInitialized() const {
+
+ return true;
+}
+
+void Duration::Swap(Duration* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void Duration::InternalSwap(Duration* other) {
+ std::swap(seconds_, other->seconds_);
+ std::swap(nanos_, other->nanos_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Duration::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = Duration_descriptor_;
+ metadata.reflection = Duration_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Duration
+
+// optional int64 seconds = 1;
+void Duration::clear_seconds() {
+ seconds_ = GOOGLE_LONGLONG(0);
+}
+ ::google::protobuf::int64 Duration::seconds() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Duration.seconds)
+ return seconds_;
+}
+ void Duration::set_seconds(::google::protobuf::int64 value) {
+
+ seconds_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Duration.seconds)
+}
+
+// optional int32 nanos = 2;
+void Duration::clear_nanos() {
+ nanos_ = 0;
+}
+ ::google::protobuf::int32 Duration::nanos() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Duration.nanos)
+ return nanos_;
+}
+ void Duration::set_nanos(::google::protobuf::int32 value) {
+
+ nanos_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Duration.nanos)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/duration.pb.h b/src/google/protobuf/duration.pb.h
new file mode 100644
index 00000000..215a52c4
--- /dev/null
+++ b/src/google/protobuf/duration.pb.h
@@ -0,0 +1,172 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/duration.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fduration_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fduration_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fduration_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fduration_2eproto();
+
+class Duration;
+
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT Duration : public ::google::protobuf::Message {
+ public:
+ Duration();
+ virtual ~Duration();
+
+ Duration(const Duration& from);
+
+ inline Duration& operator=(const Duration& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const Duration& default_instance();
+
+ void Swap(Duration* other);
+
+ // implements Message ----------------------------------------------
+
+ inline Duration* New() const { return New(NULL); }
+
+ Duration* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const Duration& from);
+ void MergeFrom(const Duration& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(Duration* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional int64 seconds = 1;
+ void clear_seconds();
+ static const int kSecondsFieldNumber = 1;
+ ::google::protobuf::int64 seconds() const;
+ void set_seconds(::google::protobuf::int64 value);
+
+ // optional int32 nanos = 2;
+ void clear_nanos();
+ static const int kNanosFieldNumber = 2;
+ ::google::protobuf::int32 nanos() const;
+ void set_nanos(::google::protobuf::int32 value);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.Duration)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::int64 seconds_;
+ ::google::protobuf::int32 nanos_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fduration_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fduration_2eproto();
+
+ void InitAsDefaultInstance();
+ static Duration* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// Duration
+
+// optional int64 seconds = 1;
+inline void Duration::clear_seconds() {
+ seconds_ = GOOGLE_LONGLONG(0);
+}
+inline ::google::protobuf::int64 Duration::seconds() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Duration.seconds)
+ return seconds_;
+}
+inline void Duration::set_seconds(::google::protobuf::int64 value) {
+
+ seconds_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Duration.seconds)
+}
+
+// optional int32 nanos = 2;
+inline void Duration::clear_nanos() {
+ nanos_ = 0;
+}
+inline ::google::protobuf::int32 Duration::nanos() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Duration.nanos)
+ return nanos_;
+}
+inline void Duration::set_nanos(::google::protobuf::int32 value) {
+
+ nanos_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Duration.nanos)
+}
+
+#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif // PROTOBUF_google_2fprotobuf_2fduration_2eproto__INCLUDED
diff --git a/src/google/protobuf/duration.proto b/src/google/protobuf/duration.proto
new file mode 100644
index 00000000..0762c3c2
--- /dev/null
+++ b/src/google/protobuf/duration.proto
@@ -0,0 +1,94 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+syntax = "proto3";
+
+package google.protobuf;
+
+option java_generate_equals_and_hash = true;
+option java_multiple_files = true;
+option java_outer_classname = "DurationProto";
+option java_package = "com.google.protobuf";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option objc_class_prefix = "GPB";
+
+// A Duration represents a signed, fixed-length span of time represented
+// as a count of seconds and fractions of seconds at nanosecond
+// resolution. It is independent of any calendar and concepts like "day"
+// or "month". It is related to Timestamp in that the difference between
+// two Timestamp values is a Duration and it can be added or subtracted
+// from a Timestamp. Range is approximately +-10,000 years.
+//
+// Example 1: Compute Duration from two Timestamps in pseudo code.
+//
+// Timestamp start = ...;
+// Timestamp end = ...;
+// Duration duration = ...;
+//
+// duration.seconds = end.seconds - start.seconds;
+// duration.nanos = end.nanos - start.nanos;
+//
+// if (duration.seconds < 0 && duration.nanos > 0) {
+// duration.seconds += 1;
+// duration.nanos -= 1000000000;
+// } else if (durations.seconds > 0 && duration.nanos < 0) {
+// duration.seconds -= 1;
+// duration.nanos += 1000000000;
+// }
+//
+// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
+//
+// Timestamp start = ...;
+// Duration duration = ...;
+// Timestamp end = ...;
+//
+// end.seconds = start.seconds + duration.seconds;
+// end.nanos = start.nanos + duration.nanos;
+//
+// if (end.nanos < 0) {
+// end.seconds -= 1;
+// end.nanos += 1000000000;
+// } else if (end.nanos >= 1000000000) {
+// end.seconds += 1;
+// end.nanos -= 1000000000;
+// }
+//
+message Duration {
+ // Signed seconds of the span of time. Must be from -315,576,000,000
+ // to +315,576,000,000 inclusive.
+ int64 seconds = 1;
+
+ // Signed fractions of a second at nanosecond resolution of the span
+ // of time. Durations less than one second are represented with a 0
+ // `seconds` field and a positive or negative `nanos` field. For durations
+ // of one second or more, a non-zero value for the `nanos` field must be
+ // of the same sign as the `seconds` field. Must be from -999,999,999
+ // to +999,999,999 inclusive.
+ int32 nanos = 2;
+}
diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc
new file mode 100644
index 00000000..1e1c2c8c
--- /dev/null
+++ b/src/google/protobuf/empty.pb.cc
@@ -0,0 +1,283 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/empty.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "google/protobuf/empty.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* Empty_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ Empty_reflection_ = NULL;
+
+} // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fempty_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto();
+ const ::google::protobuf::FileDescriptor* file =
+ ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+ "google/protobuf/empty.proto");
+ GOOGLE_CHECK(file != NULL);
+ Empty_descriptor_ = file->message_type(0);
+ static const int Empty_offsets_[1] = {
+ };
+ Empty_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ Empty_descriptor_,
+ Empty::default_instance_,
+ Empty_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(Empty),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Empty, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Empty, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+ ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+ &protobuf_AssignDesc_google_2fprotobuf_2fempty_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ Empty_descriptor_, &Empty::default_instance());
+}
+
+} // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fempty_2eproto() {
+ delete Empty::default_instance_;
+ delete Empty_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto() {
+ static bool already_here = false;
+ if (already_here) return;
+ already_here = true;
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+ "\n\033google/protobuf/empty.proto\022\017google.pr"
+ "otobuf\"\007\n\005EmptyBJ\n\023com.google.protobufB\n"
+ "EmptyProtoP\001\242\002\003GPB\252\002\036Google.Protobuf.Wel"
+ "lKnownTypesb\006proto3", 139);
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+ "google/protobuf/empty.proto", &protobuf_RegisterTypes);
+ Empty::default_instance_ = new Empty();
+ Empty::default_instance_->InitAsDefaultInstance();
+ ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fempty_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fempty_2eproto {
+ StaticDescriptorInitializer_google_2fprotobuf_2fempty_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto();
+ }
+} static_descriptor_initializer_google_2fprotobuf_2fempty_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+ GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+} // namespace
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+#endif // !_MSC_VER
+
+Empty::Empty()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.Empty)
+}
+
+void Empty::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+Empty::Empty(const Empty& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.Empty)
+}
+
+void Empty::SharedCtor() {
+ _is_default_instance_ = false;
+ _cached_size_ = 0;
+}
+
+Empty::~Empty() {
+ // @@protoc_insertion_point(destructor:google.protobuf.Empty)
+ SharedDtor();
+}
+
+void Empty::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void Empty::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Empty::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Empty_descriptor_;
+}
+
+const Empty& Empty::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto();
+ return *default_instance_;
+}
+
+Empty* Empty::default_instance_ = NULL;
+
+Empty* Empty::New(::google::protobuf::Arena* arena) const {
+ Empty* n = new Empty;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void Empty::Clear() {
+}
+
+bool Empty::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.Empty)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.Empty)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.Empty)
+ return false;
+#undef DO_
+}
+
+void Empty::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.Empty)
+ // @@protoc_insertion_point(serialize_end:google.protobuf.Empty)
+}
+
+::google::protobuf::uint8* Empty::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Empty)
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Empty)
+ return target;
+}
+
+int Empty::ByteSize() const {
+ int total_size = 0;
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void Empty::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const Empty* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Empty>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void Empty::MergeFrom(const Empty& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+}
+
+void Empty::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void Empty::CopyFrom(const Empty& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Empty::IsInitialized() const {
+
+ return true;
+}
+
+void Empty::Swap(Empty* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void Empty::InternalSwap(Empty* other) {
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Empty::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = Empty_descriptor_;
+ metadata.reflection = Empty_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Empty
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/empty.pb.h b/src/google/protobuf/empty.pb.h
new file mode 100644
index 00000000..20876bea
--- /dev/null
+++ b/src/google/protobuf/empty.pb.h
@@ -0,0 +1,130 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/empty.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fempty_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fempty_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fempty_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fempty_2eproto();
+
+class Empty;
+
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT Empty : public ::google::protobuf::Message {
+ public:
+ Empty();
+ virtual ~Empty();
+
+ Empty(const Empty& from);
+
+ inline Empty& operator=(const Empty& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const Empty& default_instance();
+
+ void Swap(Empty* other);
+
+ // implements Message ----------------------------------------------
+
+ inline Empty* New() const { return New(NULL); }
+
+ Empty* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const Empty& from);
+ void MergeFrom(const Empty& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(Empty* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.Empty)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fempty_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fempty_2eproto();
+
+ void InitAsDefaultInstance();
+ static Empty* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// Empty
+
+#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif // PROTOBUF_google_2fprotobuf_2fempty_2eproto__INCLUDED
diff --git a/src/google/protobuf/empty.proto b/src/google/protobuf/empty.proto
new file mode 100644
index 00000000..363ec175
--- /dev/null
+++ b/src/google/protobuf/empty.proto
@@ -0,0 +1,51 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+syntax = "proto3";
+
+package google.protobuf;
+
+option java_multiple_files = true;
+option java_outer_classname = "EmptyProto";
+option java_package = "com.google.protobuf";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option objc_class_prefix = "GPB";
+
+
+// A generic empty message that you can re-use to avoid defining duplicated
+// empty messages in your APIs. A typical example is to use it as the request
+// or the response type of an API method. For instance:
+//
+// service Foo {
+// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
+// }
+//
+message Empty {
+
+}
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index 49087131..649ae184 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -97,7 +97,7 @@ void Register(const MessageLite* containing_type,
int number, ExtensionInfo info) {
::google::protobuf::GoogleOnceInit(&registry_init_, &InitRegistry);
- if (!InsertIfNotPresent(registry_, make_pair(containing_type, number),
+ if (!InsertIfNotPresent(registry_, std::make_pair(containing_type, number),
info)) {
GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \""
<< containing_type->GetTypeName()
@@ -107,8 +107,9 @@ void Register(const MessageLite* containing_type,
const ExtensionInfo* FindRegisteredExtension(
const MessageLite* containing_type, int number) {
- return (registry_ == NULL) ? NULL :
- FindOrNull(*registry_, make_pair(containing_type, number));
+ return (registry_ == NULL)
+ ? NULL
+ : FindOrNull(*registry_, std::make_pair(containing_type, number));
}
} // namespace
@@ -313,7 +314,7 @@ void ExtensionSet::Add##CAMELCASE(int number, FieldType type, \
extension->is_repeated = true; \
extension->is_packed = packed; \
extension->repeated_##LOWERCASE##_value = \
- Arena::Create<RepeatedField<LOWERCASE> >(arena_, arena_); \
+ Arena::CreateMessage<RepeatedField<LOWERCASE> >(arena_); \
} else { \
GOOGLE_DCHECK_TYPE(*extension, REPEATED, UPPERCASE); \
GOOGLE_DCHECK_EQ(extension->is_packed, packed); \
@@ -358,43 +359,43 @@ void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type,
static_cast<WireFormatLite::FieldType>(field_type))) {
case WireFormatLite::CPPTYPE_INT32:
extension->repeated_int32_value =
- Arena::Create<RepeatedField<int32> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<int32> >(arena_);
break;
case WireFormatLite::CPPTYPE_INT64:
extension->repeated_int64_value =
- Arena::Create<RepeatedField<int64> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<int64> >(arena_);
break;
case WireFormatLite::CPPTYPE_UINT32:
extension->repeated_uint32_value =
- Arena::Create<RepeatedField<uint32> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<uint32> >(arena_);
break;
case WireFormatLite::CPPTYPE_UINT64:
extension->repeated_uint64_value =
- Arena::Create<RepeatedField<uint64> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<uint64> >(arena_);
break;
case WireFormatLite::CPPTYPE_DOUBLE:
extension->repeated_double_value =
- Arena::Create<RepeatedField<double> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<double> >(arena_);
break;
case WireFormatLite::CPPTYPE_FLOAT:
extension->repeated_float_value =
- Arena::Create<RepeatedField<float> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<float> >(arena_);
break;
case WireFormatLite::CPPTYPE_BOOL:
extension->repeated_bool_value =
- Arena::Create<RepeatedField<bool> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<bool> >(arena_);
break;
case WireFormatLite::CPPTYPE_ENUM:
extension->repeated_enum_value =
- Arena::Create<RepeatedField<int> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<int> >(arena_);
break;
case WireFormatLite::CPPTYPE_STRING:
extension->repeated_string_value =
- Arena::Create<RepeatedPtrField< ::std::string> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedPtrField< ::std::string> >(arena_);
break;
case WireFormatLite::CPPTYPE_MESSAGE:
extension->repeated_message_value =
- Arena::Create<RepeatedPtrField<MessageLite> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
break;
}
}
@@ -467,7 +468,7 @@ void ExtensionSet::AddEnum(int number, FieldType type,
extension->is_repeated = true;
extension->is_packed = packed;
extension->repeated_enum_value =
- Arena::Create<RepeatedField<int> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<int> >(arena_);
} else {
GOOGLE_DCHECK_TYPE(*extension, REPEATED, ENUM);
GOOGLE_DCHECK_EQ(extension->is_packed, packed);
@@ -528,7 +529,7 @@ string* ExtensionSet::AddString(int number, FieldType type,
extension->is_repeated = true;
extension->is_packed = false;
extension->repeated_string_value =
- Arena::Create<RepeatedPtrField<string> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedPtrField<string> >(arena_);
} else {
GOOGLE_DCHECK_TYPE(*extension, REPEATED, STRING);
}
@@ -631,6 +632,35 @@ void ExtensionSet::SetAllocatedMessage(int number, FieldType type,
extension->is_cleared = false;
}
+void ExtensionSet::UnsafeArenaSetAllocatedMessage(
+ int number, FieldType type, const FieldDescriptor* descriptor,
+ MessageLite* message) {
+ if (message == NULL) {
+ ClearExtension(number);
+ return;
+ }
+ Extension* extension;
+ if (MaybeNewExtension(number, descriptor, &extension)) {
+ extension->type = type;
+ GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
+ extension->is_repeated = false;
+ extension->is_lazy = false;
+ extension->message_value = message;
+ } else {
+ GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
+ if (extension->is_lazy) {
+ extension->lazymessage_value->UnsafeArenaSetAllocatedMessage(message);
+ } else {
+ if (arena_ == NULL) {
+ delete extension->message_value;
+ }
+ extension->message_value = message;
+ }
+ }
+ extension->is_cleared = false;
+}
+
+
MessageLite* ExtensionSet::ReleaseMessage(int number,
const MessageLite& prototype) {
map<int, Extension>::iterator iter = extensions_.find(number);
@@ -711,7 +741,7 @@ MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
extension->is_repeated = true;
extension->repeated_message_value =
- Arena::Create<RepeatedPtrField<MessageLite> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
} else {
GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
}
@@ -865,7 +895,7 @@ void ExtensionSet::InternalExtensionMergeFrom(
case WireFormatLite::CPPTYPE_##UPPERCASE: \
if (is_new) { \
extension->repeated_##LOWERCASE##_value = \
- Arena::Create<REPEATED_TYPE >(arena_, arena_); \
+ Arena::CreateMessage<REPEATED_TYPE >(arena_); \
} \
extension->repeated_##LOWERCASE##_value->MergeFrom( \
*other_extension.repeated_##LOWERCASE##_value); \
@@ -885,7 +915,7 @@ void ExtensionSet::InternalExtensionMergeFrom(
case WireFormatLite::CPPTYPE_MESSAGE:
if (is_new) {
extension->repeated_message_value =
- Arena::Create<RepeatedPtrField<MessageLite> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
}
// We can't call RepeatedPtrField<MessageLite>::MergeFrom() because
// it would attempt to allocate new objects.
@@ -1032,7 +1062,7 @@ void ExtensionSet::SwapExtension(ExtensionSet* other,
if (this_iter == extensions_.end()) {
if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
- extensions_.insert(make_pair(number, other_iter->second));
+ extensions_.insert(std::make_pair(number, other_iter->second));
} else {
InternalExtensionMergeFrom(number, other_iter->second);
}
@@ -1042,7 +1072,7 @@ void ExtensionSet::SwapExtension(ExtensionSet* other,
if (other_iter == other->extensions_.end()) {
if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
- other->extensions_.insert(make_pair(number, this_iter->second));
+ other->extensions_.insert(std::make_pair(number, this_iter->second));
} else {
other->InternalExtensionMergeFrom(number, this_iter->second);
}
@@ -1175,6 +1205,9 @@ bool ExtensionSet::ParseFieldWithExtensionInfo(
extension.enum_validity_check.arg, value)) {
AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed,
value, extension.descriptor);
+ } else {
+ // Invalid value. Treat as unknown.
+ field_skipper->SkipUnknownEnum(number, value);
}
}
break;
@@ -1337,7 +1370,7 @@ bool ExtensionSet::MaybeNewExtension(int number,
const FieldDescriptor* descriptor,
Extension** result) {
pair<map<int, Extension>::iterator, bool> insert_result =
- extensions_.insert(make_pair(number, Extension()));
+ extensions_.insert(std::make_pair(number, Extension()));
*result = &insert_result.first->second;
(*result)->descriptor = descriptor;
return insert_result.second;
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index 6d6702b3..c371e011 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -194,7 +194,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// directly, unless you are doing low-level memory management.
//
// When calling any of these accessors, the extension number requested
- // MUST exist in the DescriptorPool provided to the constructor. Otheriwse,
+ // MUST exist in the DescriptorPool provided to the constructor. Otherwise,
// the method will fail an assert. Normally, though, you would not call
// these directly; you would either call the generated accessors of your
// message class (e.g. GetExtension()) or you would call the accessors
@@ -262,6 +262,9 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
void SetAllocatedMessage(int number, FieldType type,
const FieldDescriptor* descriptor,
MessageLite* message);
+ void UnsafeArenaSetAllocatedMessage(int number, FieldType type,
+ const FieldDescriptor* descriptor,
+ MessageLite* message);
MessageLite* ReleaseMessage(int number, const MessageLite& prototype);
MessageLite* UnsafeArenaReleaseMessage(
int number, const MessageLite& prototype);
@@ -432,6 +435,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
const MessageLite& prototype) const = 0;
virtual MessageLite* MutableMessage(const MessageLite& prototype) = 0;
virtual void SetAllocatedMessage(MessageLite *message) = 0;
+ virtual void UnsafeArenaSetAllocatedMessage(MessageLite *message) = 0;
virtual MessageLite* ReleaseMessage(const MessageLite& prototype) = 0;
virtual MessageLite* UnsafeArenaReleaseMessage(
const MessageLite& prototype) = 0;
diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc
index 5f4ca1c3..330bd828 100644
--- a/src/google/protobuf/extension_set_heavy.cc
+++ b/src/google/protobuf/extension_set_heavy.cc
@@ -91,9 +91,10 @@ class DescriptorPoolExtensionFinder : public ExtensionFinder {
const Descriptor* containing_type_;
};
-void ExtensionSet::AppendToList(const Descriptor* containing_type,
- const DescriptorPool* pool,
- vector<const FieldDescriptor*>* output) const {
+void ExtensionSet::AppendToList(
+ const Descriptor* containing_type,
+ const DescriptorPool* pool,
+ std::vector<const FieldDescriptor*>* output) const {
for (map<int, Extension>::const_iterator iter = extensions_.begin();
iter != extensions_.end(); ++iter) {
bool has = false;
@@ -220,7 +221,7 @@ MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
extension->is_repeated = true;
extension->repeated_message_value =
- ::google::protobuf::Arena::Create<RepeatedPtrField<MessageLite> >(arena_, arena_);
+ ::google::protobuf::Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
} else {
GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
}
diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc
new file mode 100644
index 00000000..88020ef2
--- /dev/null
+++ b/src/google/protobuf/field_mask.pb.cc
@@ -0,0 +1,395 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/field_mask.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "google/protobuf/field_mask.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* FieldMask_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ FieldMask_reflection_ = NULL;
+
+} // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2ffield_5fmask_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto();
+ const ::google::protobuf::FileDescriptor* file =
+ ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+ "google/protobuf/field_mask.proto");
+ GOOGLE_CHECK(file != NULL);
+ FieldMask_descriptor_ = file->message_type(0);
+ static const int FieldMask_offsets_[1] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldMask, paths_),
+ };
+ FieldMask_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ FieldMask_descriptor_,
+ FieldMask::default_instance_,
+ FieldMask_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(FieldMask),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldMask, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldMask, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+ ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+ &protobuf_AssignDesc_google_2fprotobuf_2ffield_5fmask_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ FieldMask_descriptor_, &FieldMask::default_instance());
+}
+
+} // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2ffield_5fmask_2eproto() {
+ delete FieldMask::default_instance_;
+ delete FieldMask_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto() {
+ static bool already_here = false;
+ if (already_here) return;
+ already_here = true;
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+ "\n google/protobuf/field_mask.proto\022\017goog"
+ "le.protobuf\"\032\n\tFieldMask\022\r\n\005paths\030\001 \003(\tB"
+ "N\n\023com.google.protobufB\016FieldMaskProtoP\001"
+ "\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypesb"
+ "\006proto3", 167);
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+ "google/protobuf/field_mask.proto", &protobuf_RegisterTypes);
+ FieldMask::default_instance_ = new FieldMask();
+ FieldMask::default_instance_->InitAsDefaultInstance();
+ ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2ffield_5fmask_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2ffield_5fmask_2eproto {
+ StaticDescriptorInitializer_google_2fprotobuf_2ffield_5fmask_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto();
+ }
+} static_descriptor_initializer_google_2fprotobuf_2ffield_5fmask_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+ GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+} // namespace
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int FieldMask::kPathsFieldNumber;
+#endif // !_MSC_VER
+
+FieldMask::FieldMask()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.FieldMask)
+}
+
+void FieldMask::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+FieldMask::FieldMask(const FieldMask& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldMask)
+}
+
+void FieldMask::SharedCtor() {
+ _is_default_instance_ = false;
+ ::google::protobuf::internal::GetEmptyString();
+ _cached_size_ = 0;
+}
+
+FieldMask::~FieldMask() {
+ // @@protoc_insertion_point(destructor:google.protobuf.FieldMask)
+ SharedDtor();
+}
+
+void FieldMask::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void FieldMask::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* FieldMask::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return FieldMask_descriptor_;
+}
+
+const FieldMask& FieldMask::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto();
+ return *default_instance_;
+}
+
+FieldMask* FieldMask::default_instance_ = NULL;
+
+FieldMask* FieldMask::New(::google::protobuf::Arena* arena) const {
+ FieldMask* n = new FieldMask;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void FieldMask::Clear() {
+ paths_.Clear();
+}
+
+bool FieldMask::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.FieldMask)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // repeated string paths = 1;
+ case 1: {
+ if (tag == 10) {
+ parse_paths:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->add_paths()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->paths(this->paths_size() - 1).data(),
+ this->paths(this->paths_size() - 1).length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.FieldMask.paths");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(10)) goto parse_paths;
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.FieldMask)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.FieldMask)
+ return false;
+#undef DO_
+}
+
+void FieldMask::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.FieldMask)
+ // repeated string paths = 1;
+ for (int i = 0; i < this->paths_size(); i++) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->paths(i).data(), this->paths(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.FieldMask.paths");
+ ::google::protobuf::internal::WireFormatLite::WriteString(
+ 1, this->paths(i), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.FieldMask)
+}
+
+::google::protobuf::uint8* FieldMask::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldMask)
+ // repeated string paths = 1;
+ for (int i = 0; i < this->paths_size(); i++) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->paths(i).data(), this->paths(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.FieldMask.paths");
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteStringToArray(1, this->paths(i), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldMask)
+ return target;
+}
+
+int FieldMask::ByteSize() const {
+ int total_size = 0;
+
+ // repeated string paths = 1;
+ total_size += 1 * this->paths_size();
+ for (int i = 0; i < this->paths_size(); i++) {
+ total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->paths(i));
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void FieldMask::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const FieldMask* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const FieldMask>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void FieldMask::MergeFrom(const FieldMask& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ paths_.MergeFrom(from.paths_);
+}
+
+void FieldMask::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void FieldMask::CopyFrom(const FieldMask& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool FieldMask::IsInitialized() const {
+
+ return true;
+}
+
+void FieldMask::Swap(FieldMask* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void FieldMask::InternalSwap(FieldMask* other) {
+ paths_.UnsafeArenaSwap(&other->paths_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata FieldMask::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = FieldMask_descriptor_;
+ metadata.reflection = FieldMask_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FieldMask
+
+// repeated string paths = 1;
+int FieldMask::paths_size() const {
+ return paths_.size();
+}
+void FieldMask::clear_paths() {
+ paths_.Clear();
+}
+ const ::std::string& FieldMask::paths(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldMask.paths)
+ return paths_.Get(index);
+}
+ ::std::string* FieldMask::mutable_paths(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FieldMask.paths)
+ return paths_.Mutable(index);
+}
+ void FieldMask::set_paths(int index, const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths)
+ paths_.Mutable(index)->assign(value);
+}
+ void FieldMask::set_paths(int index, const char* value) {
+ paths_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FieldMask.paths)
+}
+ void FieldMask::set_paths(int index, const char* value, size_t size) {
+ paths_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldMask.paths)
+}
+ ::std::string* FieldMask::add_paths() {
+ return paths_.Add();
+}
+ void FieldMask::add_paths(const ::std::string& value) {
+ paths_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths)
+}
+ void FieldMask::add_paths(const char* value) {
+ paths_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.FieldMask.paths)
+}
+ void FieldMask::add_paths(const char* value, size_t size) {
+ paths_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.FieldMask.paths)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+FieldMask::paths() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FieldMask.paths)
+ return paths_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+FieldMask::mutable_paths() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldMask.paths)
+ return &paths_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h
new file mode 100644
index 00000000..7189fd79
--- /dev/null
+++ b/src/google/protobuf/field_mask.pb.h
@@ -0,0 +1,201 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/field_mask.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2ffield_5fmask_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2ffield_5fmask_2eproto();
+
+class FieldMask;
+
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT FieldMask : public ::google::protobuf::Message {
+ public:
+ FieldMask();
+ virtual ~FieldMask();
+
+ FieldMask(const FieldMask& from);
+
+ inline FieldMask& operator=(const FieldMask& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const FieldMask& default_instance();
+
+ void Swap(FieldMask* other);
+
+ // implements Message ----------------------------------------------
+
+ inline FieldMask* New() const { return New(NULL); }
+
+ FieldMask* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const FieldMask& from);
+ void MergeFrom(const FieldMask& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(FieldMask* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // repeated string paths = 1;
+ int paths_size() const;
+ void clear_paths();
+ static const int kPathsFieldNumber = 1;
+ const ::std::string& paths(int index) const;
+ ::std::string* mutable_paths(int index);
+ void set_paths(int index, const ::std::string& value);
+ void set_paths(int index, const char* value);
+ void set_paths(int index, const char* value, size_t size);
+ ::std::string* add_paths();
+ void add_paths(const ::std::string& value);
+ void add_paths(const char* value);
+ void add_paths(const char* value, size_t size);
+ const ::google::protobuf::RepeatedPtrField< ::std::string>& paths() const;
+ ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_paths();
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.FieldMask)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::RepeatedPtrField< ::std::string> paths_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2ffield_5fmask_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2ffield_5fmask_2eproto();
+
+ void InitAsDefaultInstance();
+ static FieldMask* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// FieldMask
+
+// repeated string paths = 1;
+inline int FieldMask::paths_size() const {
+ return paths_.size();
+}
+inline void FieldMask::clear_paths() {
+ paths_.Clear();
+}
+inline const ::std::string& FieldMask::paths(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldMask.paths)
+ return paths_.Get(index);
+}
+inline ::std::string* FieldMask::mutable_paths(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FieldMask.paths)
+ return paths_.Mutable(index);
+}
+inline void FieldMask::set_paths(int index, const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths)
+ paths_.Mutable(index)->assign(value);
+}
+inline void FieldMask::set_paths(int index, const char* value) {
+ paths_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FieldMask.paths)
+}
+inline void FieldMask::set_paths(int index, const char* value, size_t size) {
+ paths_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldMask.paths)
+}
+inline ::std::string* FieldMask::add_paths() {
+ return paths_.Add();
+}
+inline void FieldMask::add_paths(const ::std::string& value) {
+ paths_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths)
+}
+inline void FieldMask::add_paths(const char* value) {
+ paths_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.FieldMask.paths)
+}
+inline void FieldMask::add_paths(const char* value, size_t size) {
+ paths_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.FieldMask.paths)
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+FieldMask::paths() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FieldMask.paths)
+ return paths_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+FieldMask::mutable_paths() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldMask.paths)
+ return &paths_;
+}
+
+#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif // PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto__INCLUDED
diff --git a/src/google/protobuf/field_mask.proto b/src/google/protobuf/field_mask.proto
new file mode 100644
index 00000000..c19f4410
--- /dev/null
+++ b/src/google/protobuf/field_mask.proto
@@ -0,0 +1,163 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+syntax = "proto3";
+
+package google.protobuf;
+
+option java_multiple_files = true;
+option java_outer_classname = "FieldMaskProto";
+option java_package = "com.google.protobuf";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option objc_class_prefix = "GPB";
+
+
+// `FieldMask` represents a set of symbolic field paths, for example:
+//
+// paths: "f.a"
+// paths: "f.b.d"
+//
+// Here `f` represents a field in some root message, `a` and `b`
+// fields in the message found in `f`, and `d` a field found in the
+// message in `f.b`.
+//
+// Field masks are used to specify a subset of fields that should be
+// returned by a get operation or modified by an update operation.
+// Field masks also have a custom JSON encoding (see below).
+//
+// # Field Masks in Projections
+// When used in the context of a projection, a response message or
+// sub-message is filtered by the API to only contain those fields as
+// specified in the mask. For example, if the mask in the previous
+// example is applied to a response message as follows:
+//
+// f {
+// a : 22
+// b {
+// d : 1
+// x : 2
+// }
+// y : 13
+// }
+// z: 8
+//
+// The result will not contain specific values for fields x,y and z
+// (there value will be set to the default, and omitted in proto text
+// output):
+//
+//
+// f {
+// a : 22
+// b {
+// d : 1
+// }
+// }
+//
+// A repeated field is not allowed except at the last position of a
+// field mask.
+//
+// If a FieldMask object is not present in a get operation, the
+// operation applies to all fields (as if a FieldMask of all fields
+// had been specified).
+//
+// Note that a field mask does not necessarily applies to the
+// top-level response message. In case of a REST get operation, the
+// field mask applies directly to the response, but in case of a REST
+// list operation, the mask instead applies to each individual message
+// in the returned resource list. In case of a REST custom method,
+// other definitions may be used. Where the mask applies will be
+// clearly documented together with its declaration in the API. In
+// any case, the effect on the returned resource/resources is required
+// behavior for APIs.
+//
+// # Field Masks in Update Operations
+// A field mask in update operations specifies which fields of the
+// targeted resource are going to be updated. The API is required
+// to only change the values of the fields as specified in the mask
+// and leave the others untouched. If a resource is passed in to
+// describe the updated values, the API ignores the values of all
+// fields not covered by the mask.
+//
+// In order to reset a field's value to the default, the field must
+// be in the mask and set to the default value in the provided resource.
+// Hence, in order to reset all fields of a resource, provide a default
+// instance of the resource and set all fields in the mask, or do
+// not provide a mask as described below.
+//
+// If a field mask is not present on update, the operation applies to
+// all fields (as if a field mask of all fields has been specified).
+// Note that in the presence of schema evolution, this may mean that
+// fields the client does not know and has therefore not filled into
+// the request will be reset to their default. If this is unwanted
+// behavior, a specific service may require a client to always specify
+// a field mask, producing an error if not.
+//
+// As with get operations, the location of the resource which
+// describes the updated values in the request message depends on the
+// operation kind. In any case, the effect of the field mask is
+// required to be honored by the API.
+//
+// ## Considerations for HTTP REST
+// The HTTP kind of an update operation which uses a field mask must
+// be set to PATCH instead of PUT in order to satisfy HTTP semantics
+// (PUT must only be used for full updates).
+//
+// # JSON Encoding of Field Masks
+// In JSON, a field mask is encoded as a single string where paths are
+// separated by a comma. Fields name in each path are converted
+// to/from lower-camel naming conventions.
+//
+// As an example, consider the following message declarations:
+//
+// message Profile {
+// User user = 1;
+// Photo photo = 2;
+// }
+// message User {
+// string display_name = 1;
+// string address = 2;
+// }
+//
+// In proto a field mask for `Profile` may look as such:
+//
+// mask {
+// paths: "user.display_name"
+// paths: "photo"
+// }
+//
+// In JSON, the same mask is represented as below:
+//
+// {
+// mask: "user.displayName,photo"
+// }
+//
+message FieldMask {
+ // The set of field mask paths.
+ repeated string paths = 1;
+}
diff --git a/src/google/protobuf/generated_enum_reflection.h b/src/google/protobuf/generated_enum_reflection.h
index 3852cea5..fdcdc277 100644
--- a/src/google/protobuf/generated_enum_reflection.h
+++ b/src/google/protobuf/generated_enum_reflection.h
@@ -42,6 +42,7 @@
#include <string>
#include <google/protobuf/stubs/template_util.h>
+#include <google/protobuf/generated_enum_util.h>
namespace google {
namespace protobuf {
@@ -50,10 +51,6 @@ namespace protobuf {
namespace protobuf {
-// This type trait can be used to cause templates to only match proto2 enum
-// types.
-template <typename T> struct is_proto_enum : ::google::protobuf::internal::false_type {};
-
// Returns the EnumDescriptor for enum type E, which must be a
// proto-declared enum type. Code generated by the protocol compiler
// will include specializations of this template for each enum type declared.
diff --git a/src/google/protobuf/generated_enum_util.h b/src/google/protobuf/generated_enum_util.h
new file mode 100644
index 00000000..e4242055
--- /dev/null
+++ b/src/google/protobuf/generated_enum_util.h
@@ -0,0 +1,46 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
+#define GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
+
+#include <google/protobuf/stubs/template_util.h>
+
+namespace google {
+namespace protobuf {
+
+// This type trait can be used to cause templates to only match proto2 enum
+// types.
+template <typename T> struct is_proto_enum : ::google::protobuf::internal::false_type {};
+
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index b500b9c5..412c48a1 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -247,8 +247,14 @@ namespace {
UnknownFieldSet* empty_unknown_field_set_ = NULL;
GOOGLE_PROTOBUF_DECLARE_ONCE(empty_unknown_field_set_once_);
+void DeleteEmptyUnknownFieldSet() {
+ delete empty_unknown_field_set_;
+ empty_unknown_field_set_ = NULL;
+}
+
void InitEmptyUnknownFieldSet() {
empty_unknown_field_set_ = new UnknownFieldSet;
+ internal::OnShutdown(&DeleteEmptyUnknownFieldSet);
}
const UnknownFieldSet& GetEmptyUnknownFieldSet() {
@@ -989,6 +995,7 @@ void GeneratedMessageReflection::ListFields(
// Optimization: The default instance never has any fields set.
if (&message == default_instance_) return;
+ output->reserve(descriptor_->field_count());
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->is_repeated()) {
@@ -1012,7 +1019,7 @@ void GeneratedMessageReflection::ListFields(
}
// ListFields() must sort output by field number.
- sort(output->begin(), output->end(), FieldNumberSorter());
+ std::sort(output->begin(), output->end(), FieldNumberSorter());
}
// -------------------------------------------------------------------
@@ -1428,6 +1435,8 @@ const Message& GeneratedMessageReflection::GetMessage(
Message* GeneratedMessageReflection::MutableMessage(
Message* message, const FieldDescriptor* field,
MessageFactory* factory) const {
+ USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
+
if (factory == NULL) factory = message_factory_;
if (field->is_extension()) {
@@ -1966,26 +1975,28 @@ inline void GeneratedMessageReflection::ClearOneof(
uint32 oneof_case = GetOneofCase(*message, oneof_descriptor);
if (oneof_case > 0) {
const FieldDescriptor* field = descriptor_->FindFieldByNumber(oneof_case);
- switch (field->cpp_type()) {
- case FieldDescriptor::CPPTYPE_STRING: {
- switch (field->options().ctype()) {
- default: // TODO(kenton): Support other string reps.
- case FieldOptions::STRING: {
- const string* default_ptr =
- &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
- MutableField<ArenaStringPtr>(message, field)->
- Destroy(default_ptr, GetArena(message));
- break;
+ if (GetArena(message) == NULL) {
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_STRING: {
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING: {
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+ MutableField<ArenaStringPtr>(message, field)->
+ Destroy(default_ptr, GetArena(message));
+ break;
+ }
}
+ break;
}
- break;
- }
- case FieldDescriptor::CPPTYPE_MESSAGE:
- delete *MutableRaw<Message*>(message, field);
- break;
- default:
- break;
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ delete *MutableRaw<Message*>(message, field);
+ break;
+ default:
+ break;
+ }
}
*MutableOneofCase(message, oneof_descriptor) = 0;
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index 4dddf6c7..dc8abb98 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -40,6 +40,7 @@
#include <string>
#include <vector>
+#include <google/protobuf/stubs/casts.h>
#include <google/protobuf/stubs/common.h>
// TODO(jasonh): Remove this once the compiler change to directly include this
// is released to components.
@@ -597,6 +598,42 @@ inline To dynamic_cast_if_available(From from) {
#endif
}
+// Tries to downcast this message to a generated message type.
+// Returns NULL if this class is not an instance of T.
+//
+// This is like dynamic_cast_if_available, except it works even when
+// dynamic_cast is not available by using Reflection. However it only works
+// with Message objects.
+//
+// TODO(haberman): can we remove dynamic_cast_if_available in favor of this?
+template <typename T>
+T* DynamicCastToGenerated(const Message* from) {
+ // Compile-time assert that T is a generated type that has a
+ // default_instance() accessor, but avoid actually calling it.
+ const T&(*get_default_instance)() = &T::default_instance;
+ (void)get_default_instance;
+
+ // Compile-time assert that T is a subclass of google::protobuf::Message.
+ const Message* unused = static_cast<T*>(NULL);
+ (void)unused;
+
+#if defined(GOOGLE_PROTOBUF_NO_RTTI) || \
+ (defined(_MSC_VER) && !defined(_CPPRTTI))
+ bool ok = &T::default_instance() ==
+ from->GetReflection()->GetMessageFactory()->GetPrototype(
+ from->GetDescriptor());
+ return ok ? down_cast<T*>(from) : NULL;
+#else
+ return dynamic_cast<T*>(from);
+#endif
+}
+
+template <typename T>
+T* DynamicCastToGenerated(Message* from) {
+ const Message* message_const = from;
+ return const_cast<T*>(DynamicCastToGenerated<const T>(message_const));
+}
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
index 678f92a7..6357e27d 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/src/google/protobuf/generated_message_util.h
@@ -47,6 +47,10 @@
namespace google {
namespace protobuf {
+
+class Arena;
+namespace io { class CodedInputStream; }
+
namespace internal {
@@ -106,6 +110,15 @@ template <class Type> bool AllAreInitialized(const Type& t) {
return true;
}
+class ArenaString;
+
+// Read a length (varint32), followed by a string, from *input. Return a
+// pointer to a copy of the string that resides in *arena. Requires both
+// args to be non-NULL. If something goes wrong while reading the data
+// then NULL is returned (e.g., input does not start with a valid varint).
+ArenaString* ReadArenaString(::google::protobuf::io::CodedInputStream* input,
+ ::google::protobuf::Arena* arena);
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index df88205c..3b8650d6 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -153,7 +153,12 @@ void CodedInputStream::PopLimit(Limit limit) {
std::pair<CodedInputStream::Limit, int>
CodedInputStream::IncrementRecursionDepthAndPushLimit(int byte_limit) {
- return make_pair(PushLimit(byte_limit), --recursion_budget_);
+ return std::make_pair(PushLimit(byte_limit), --recursion_budget_);
+}
+
+CodedInputStream::Limit CodedInputStream::ReadLengthAndPushLimit() {
+ uint32 length;
+ return PushLimit(ReadVarint32(&length) ? length : 0);
}
bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) {
@@ -164,6 +169,12 @@ bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) {
return result;
}
+bool CodedInputStream::CheckEntireMessageConsumedAndPopLimit(Limit limit) {
+ bool result = ConsumedEntireMessage();
+ PopLimit(limit);
+ return result;
+}
+
int CodedInputStream::BytesUntilLimit() const {
if (current_limit_ == INT_MAX) return -1;
int current_position = CurrentPosition();
@@ -245,20 +256,7 @@ bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) {
}
bool CodedInputStream::ReadRaw(void* buffer, int size) {
- int current_buffer_size;
- while ((current_buffer_size = BufferSize()) < size) {
- // Reading past end of buffer. Copy what we have, then refresh.
- memcpy(buffer, buffer_, current_buffer_size);
- buffer = reinterpret_cast<uint8*>(buffer) + current_buffer_size;
- size -= current_buffer_size;
- Advance(current_buffer_size);
- if (!Refresh()) return false;
- }
-
- memcpy(buffer, buffer_, size);
- Advance(size);
-
- return true;
+ return InternalReadRawInline(buffer, size);
}
bool CodedInputStream::ReadString(string* buffer, int size) {
@@ -336,17 +334,23 @@ bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) {
namespace {
-inline const uint8* ReadVarint32FromArray(
- const uint8* buffer, uint32* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
-inline const uint8* ReadVarint32FromArray(const uint8* buffer, uint32* value) {
+// Read a varint from the given buffer, write it to *value, and return a pair.
+// The first part of the pair is true iff the read was successful. The second
+// part is buffer + (number of bytes read). This function is always inlined,
+// so returning a pair is costless.
+inline ::std::pair<bool, const uint8*> ReadVarint32FromArray(
+ uint32 first_byte, const uint8* buffer,
+ uint32* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+inline ::std::pair<bool, const uint8*> ReadVarint32FromArray(
+ uint32 first_byte, const uint8* buffer, uint32* value) {
// Fast path: We have enough bytes left in the buffer to guarantee that
// this read won't cross the end, so we can skip the checks.
+ GOOGLE_DCHECK_EQ(*buffer, first_byte);
+ GOOGLE_DCHECK_EQ(first_byte & 0x80, 0x80) << first_byte;
const uint8* ptr = buffer;
uint32 b;
- uint32 result;
-
- b = *(ptr++); result = b ; if (!(b & 0x80)) goto done;
- result -= 0x80;
+ uint32 result = first_byte - 0x80;
+ ++ptr; // We just processed the first byte. Move on to the second.
b = *(ptr++); result += b << 7; if (!(b & 0x80)) goto done;
result -= 0x80 << 7;
b = *(ptr++); result += b << 14; if (!(b & 0x80)) goto done;
@@ -364,38 +368,42 @@ inline const uint8* ReadVarint32FromArray(const uint8* buffer, uint32* value) {
// We have overrun the maximum size of a varint (10 bytes). Assume
// the data is corrupt.
- return NULL;
+ return std::make_pair(false, ptr);
done:
*value = result;
- return ptr;
+ return std::make_pair(true, ptr);
}
} // namespace
bool CodedInputStream::ReadVarint32Slow(uint32* value) {
- uint64 result;
// Directly invoke ReadVarint64Fallback, since we already tried to optimize
// for one-byte varints.
- if (!ReadVarint64Fallback(&result)) return false;
- *value = (uint32)result;
- return true;
+ std::pair<uint64, bool> p = ReadVarint64Fallback();
+ *value = static_cast<uint32>(p.first);
+ return p.second;
}
-bool CodedInputStream::ReadVarint32Fallback(uint32* value) {
+int64 CodedInputStream::ReadVarint32Fallback(uint32 first_byte_or_zero) {
if (BufferSize() >= kMaxVarintBytes ||
// Optimization: We're also safe if the buffer is non-empty and it ends
// with a byte that would terminate a varint.
(buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
- const uint8* end = ReadVarint32FromArray(buffer_, value);
- if (end == NULL) return false;
- buffer_ = end;
- return true;
+ GOOGLE_DCHECK_NE(first_byte_or_zero, 0)
+ << "Caller should provide us with *buffer_ when buffer is non-empty";
+ uint32 temp;
+ ::std::pair<bool, const uint8*> p =
+ ReadVarint32FromArray(first_byte_or_zero, buffer_, &temp);
+ if (!p.first) return -1;
+ buffer_ = p.second;
+ return temp;
} else {
// Really slow case: we will incur the cost of an extra function call here,
// but moving this out of line reduces the size of this function, which
// improves the common case. In micro benchmarks, this is worth about 10-15%
- return ReadVarint32Slow(value);
+ uint32 temp;
+ return ReadVarint32Slow(&temp) ? static_cast<int64>(temp) : -1;
}
}
@@ -425,18 +433,24 @@ uint32 CodedInputStream::ReadTagSlow() {
return static_cast<uint32>(result);
}
-uint32 CodedInputStream::ReadTagFallback() {
+uint32 CodedInputStream::ReadTagFallback(uint32 first_byte_or_zero) {
const int buf_size = BufferSize();
if (buf_size >= kMaxVarintBytes ||
// Optimization: We're also safe if the buffer is non-empty and it ends
// with a byte that would terminate a varint.
(buf_size > 0 && !(buffer_end_[-1] & 0x80))) {
+ GOOGLE_DCHECK_EQ(first_byte_or_zero, buffer_[0]);
+ if (first_byte_or_zero == 0) {
+ ++buffer_;
+ return 0;
+ }
uint32 tag;
- const uint8* end = ReadVarint32FromArray(buffer_, &tag);
- if (end == NULL) {
+ ::std::pair<bool, const uint8*> p =
+ ReadVarint32FromArray(first_byte_or_zero, buffer_, &tag);
+ if (!p.first) {
return 0;
}
- buffer_ = end;
+ buffer_ = p.second;
return tag;
} else {
// We are commonly at a limit when attempting to read tags. Try to quickly
@@ -479,7 +493,7 @@ bool CodedInputStream::ReadVarint64Slow(uint64* value) {
return true;
}
-bool CodedInputStream::ReadVarint64Fallback(uint64* value) {
+std::pair<uint64, bool> CodedInputStream::ReadVarint64Fallback() {
if (BufferSize() >= kMaxVarintBytes ||
// Optimization: We're also safe if the buffer is non-empty and it ends
// with a byte that would terminate a varint.
@@ -517,16 +531,18 @@ bool CodedInputStream::ReadVarint64Fallback(uint64* value) {
// We have overrun the maximum size of a varint (10 bytes). The data
// must be corrupt.
- return false;
+ return std::make_pair(0, false);
done:
Advance(ptr - buffer_);
- *value = (static_cast<uint64>(part0) ) |
- (static_cast<uint64>(part1) << 28) |
- (static_cast<uint64>(part2) << 56);
- return true;
+ return std::make_pair((static_cast<uint64>(part0)) |
+ (static_cast<uint64>(part1) << 28) |
+ (static_cast<uint64>(part2) << 56),
+ true);
} else {
- return ReadVarint64Slow(value);
+ uint64 temp;
+ bool success = ReadVarint64Slow(&temp);
+ return std::make_pair(temp, success);
}
}
@@ -613,8 +629,15 @@ CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output)
}
CodedOutputStream::~CodedOutputStream() {
+ Trim();
+}
+
+void CodedOutputStream::Trim() {
if (buffer_size_ > 0) {
output_->BackUp(buffer_size_);
+ total_bytes_ -= buffer_size_;
+ buffer_size_ = 0;
+ buffer_ = NULL;
}
}
@@ -662,12 +685,7 @@ void CodedOutputStream::WriteAliasedRaw(const void* data, int size) {
) {
WriteRaw(data, size);
} else {
- if (buffer_size_ > 0) {
- output_->BackUp(buffer_size_);
- total_bytes_ -= buffer_size_;
- buffer_ = NULL;
- buffer_size_ = 0;
- }
+ Trim();
total_bytes_ += size;
had_error_ |= !output_->WriteAliasedRaw(data, size);
@@ -704,61 +722,12 @@ void CodedOutputStream::WriteLittleEndian64(uint64 value) {
}
}
-inline uint8* CodedOutputStream::WriteVarint32FallbackToArrayInline(
- uint32 value, uint8* target) {
- target[0] = static_cast<uint8>(value | 0x80);
- if (value >= (1 << 7)) {
- target[1] = static_cast<uint8>((value >> 7) | 0x80);
- if (value >= (1 << 14)) {
- target[2] = static_cast<uint8>((value >> 14) | 0x80);
- if (value >= (1 << 21)) {
- target[3] = static_cast<uint8>((value >> 21) | 0x80);
- if (value >= (1 << 28)) {
- target[4] = static_cast<uint8>(value >> 28);
- return target + 5;
- } else {
- target[3] &= 0x7F;
- return target + 4;
- }
- } else {
- target[2] &= 0x7F;
- return target + 3;
- }
- } else {
- target[1] &= 0x7F;
- return target + 2;
- }
- } else {
- target[0] &= 0x7F;
- return target + 1;
- }
-}
-
-void CodedOutputStream::WriteVarint32(uint32 value) {
- if (buffer_size_ >= kMaxVarint32Bytes) {
- // Fast path: We have enough bytes left in the buffer to guarantee that
- // this write won't cross the end, so we can skip the checks.
- uint8* target = buffer_;
- uint8* end = WriteVarint32FallbackToArrayInline(value, target);
- int size = end - target;
- Advance(size);
- } else {
- // Slow path: This write might cross the end of the buffer, so we
- // compose the bytes first then use WriteRaw().
- uint8 bytes[kMaxVarint32Bytes];
- int size = 0;
- while (value > 0x7F) {
- bytes[size++] = (static_cast<uint8>(value) & 0x7F) | 0x80;
- value >>= 7;
- }
- bytes[size++] = static_cast<uint8>(value) & 0x7F;
- WriteRaw(bytes, size);
- }
-}
-
-uint8* CodedOutputStream::WriteVarint32FallbackToArray(
- uint32 value, uint8* target) {
- return WriteVarint32FallbackToArrayInline(value, target);
+void CodedOutputStream::WriteVarint32SlowPath(uint32 value) {
+ uint8 bytes[kMaxVarint32Bytes];
+ uint8* target = &bytes[0];
+ uint8* end = WriteVarint32ToArray(value, target);
+ int size = end - target;
+ WriteRaw(bytes, size);
}
inline uint8* CodedOutputStream::WriteVarint64ToArrayInline(
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index 978cc19d..ad351dc3 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -112,8 +112,8 @@
#include <string>
#include <utility>
#ifdef _MSC_VER
- #if defined(_M_IX86) && \
- !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
+ // Assuming windows is always little-endian.
+ #if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
#define PROTOBUF_LITTLE_ENDIAN 1
#endif
#if _MSC_VER >= 1300
@@ -197,6 +197,11 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// Read raw bytes, copying them into the given buffer.
bool ReadRaw(void* buffer, int size);
+ // Like the above, with inlined optimizations. This should only be used
+ // by the protobuf implementation.
+ inline bool InternalReadRawInline(void* buffer,
+ int size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+
// Like ReadRaw, but reads into a string.
//
// Implementation Note: ReadString() grows the string gradually as it
@@ -387,9 +392,14 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// under the limit, false if it has gone over.
bool IncrementRecursionDepth();
- // Decrements the recursion depth.
+ // Decrements the recursion depth if possible.
void DecrementRecursionDepth();
+ // Decrements the recursion depth blindly. This is faster than
+ // DecrementRecursionDepth(). It should be used only if all previous
+ // increments to recursion depth were successful.
+ void UnsafeDecrementRecursionDepth();
+
// Shorthand for make_pair(PushLimit(byte_limit), --recursion_budget_).
// Using this can reduce code size and complexity in some cases. The caller
// is expected to check that the second part of the result is non-negative (to
@@ -398,15 +408,25 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
std::pair<CodedInputStream::Limit, int> IncrementRecursionDepthAndPushLimit(
int byte_limit);
+ // Shorthand for PushLimit(ReadVarint32(&length) ? length : 0).
+ Limit ReadLengthAndPushLimit();
+
// Helper that is equivalent to: {
// bool result = ConsumedEntireMessage();
// PopLimit(limit);
- // DecrementRecursionDepth();
+ // UnsafeDecrementRecursionDepth();
// return result; }
// Using this can reduce code size and complexity in some cases.
// Do not use unless the current recursion depth is greater than zero.
bool DecrementRecursionDepthAndPopLimit(Limit limit);
+ // Helper that is equivalent to: {
+ // bool result = ConsumedEntireMessage();
+ // PopLimit(limit);
+ // return result; }
+ // Using this can reduce code size and complexity in some cases.
+ bool CheckEntireMessageConsumedAndPopLimit(Limit limit);
+
// Extension Registry ----------------------------------------------
// ADVANCED USAGE: 99.9% of people can ignore this section.
//
@@ -568,9 +588,13 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// optimization. The Slow method is yet another fallback when the buffer is
// not large enough. Making the slow path out-of-line speeds up the common
// case by 10-15%. The slow path is fairly uncommon: it only triggers when a
- // message crosses multiple buffers.
- bool ReadVarint32Fallback(uint32* value);
- bool ReadVarint64Fallback(uint64* value);
+ // message crosses multiple buffers. Note: ReadVarint32Fallback() and
+ // ReadVarint64Fallback() are called frequently and generally not inlined, so
+ // they have been optimized to avoid "out" parameters. The former returns -1
+ // if it fails and the uint32 it read otherwise. The latter has a bool
+ // indicating success or failure as part of its return type.
+ int64 ReadVarint32Fallback(uint32 first_byte_or_zero);
+ std::pair<uint64, bool> ReadVarint64Fallback();
bool ReadVarint32Slow(uint32* value);
bool ReadVarint64Slow(uint64* value);
bool ReadLittleEndian32Fallback(uint32* value);
@@ -578,7 +602,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// Fallback/slow methods for reading tags. These do not update last_tag_,
// but will set legitimate_message_end_ if we are at the end of the input
// stream.
- uint32 ReadTagFallback();
+ uint32 ReadTagFallback(uint32 first_byte_or_zero);
uint32 ReadTagSlow();
bool ReadStringFallback(string* buffer, int size);
@@ -647,6 +671,13 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// ZeroCopyOutputStream immediately after the last byte written.
~CodedOutputStream();
+ // Trims any unused space in the underlying buffer so that its size matches
+ // the number of bytes written by this stream. The underlying buffer will
+ // automatically be trimmed when this stream is destroyed; this call is only
+ // necessary if the underlying buffer is accessed *before* the stream is
+ // destroyed.
+ void Trim();
+
// Skips a number of bytes, leaving the bytes unmodified in the underlying
// buffer. Returns false if an underlying write error occurs. This is
// mainly useful with GetDirectBufferPointer().
@@ -789,7 +820,9 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// ZeroCopyOutputStream supports it.
void WriteAliasedRaw(const void* buffer, int size);
- static uint8* WriteVarint32FallbackToArray(uint32 value, uint8* target);
+ // If this write might cross the end of the buffer, we compose the bytes first
+ // then use WriteRaw().
+ void WriteVarint32SlowPath(uint32 value);
// Always-inlined versions of WriteVarint* functions so that code can be
// reused, while still controlling size. For instance, WriteVarint32ToArray()
@@ -798,8 +831,6 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// WriteVarint32FallbackToArray. Meanwhile, WriteVarint32() is already
// out-of-line, so it should just invoke this directly to avoid any extra
// function call overhead.
- static uint8* WriteVarint32FallbackToArrayInline(
- uint32 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
static uint8* WriteVarint64ToArrayInline(
uint64 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
@@ -811,13 +842,18 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// methods optimize for that case.
inline bool CodedInputStream::ReadVarint32(uint32* value) {
- if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && *buffer_ < 0x80) {
- *value = *buffer_;
- Advance(1);
- return true;
- } else {
- return ReadVarint32Fallback(value);
+ uint32 v = 0;
+ if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) {
+ v = *buffer_;
+ if (v < 0x80) {
+ *value = v;
+ Advance(1);
+ return true;
+ }
}
+ int64 result = ReadVarint32Fallback(v);
+ *value = static_cast<uint32>(result);
+ return result >= 0;
}
inline bool CodedInputStream::ReadVarint64(uint64* value) {
@@ -825,9 +861,10 @@ inline bool CodedInputStream::ReadVarint64(uint64* value) {
*value = *buffer_;
Advance(1);
return true;
- } else {
- return ReadVarint64Fallback(value);
}
+ std::pair<uint64, bool> p = ReadVarint64Fallback();
+ *value = p.first;
+ return p.second;
}
// static
@@ -896,14 +933,17 @@ inline bool CodedInputStream::ReadLittleEndian64(uint64* value) {
}
inline uint32 CodedInputStream::ReadTag() {
- if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && buffer_[0] < 0x80) {
- last_tag_ = buffer_[0];
- Advance(1);
- return last_tag_;
- } else {
- last_tag_ = ReadTagFallback();
- return last_tag_;
+ uint32 v = 0;
+ if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) {
+ v = *buffer_;
+ if (v < 0x80) {
+ last_tag_ = v;
+ Advance(1);
+ return v;
+ }
}
+ last_tag_ = ReadTagFallback(v);
+ return last_tag_;
}
inline std::pair<uint32, bool> CodedInputStream::ReadTagWithCutoff(
@@ -911,15 +951,17 @@ inline std::pair<uint32, bool> CodedInputStream::ReadTagWithCutoff(
// In performance-sensitive code we can expect cutoff to be a compile-time
// constant, and things like "cutoff >= kMax1ByteVarint" to be evaluated at
// compile time.
+ uint32 first_byte_or_zero = 0;
if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) {
// Hot case: buffer_ non_empty, buffer_[0] in [1, 128).
// TODO(gpike): Is it worth rearranging this? E.g., if the number of fields
// is large enough then is it better to check for the two-byte case first?
+ first_byte_or_zero = buffer_[0];
if (static_cast<int8>(buffer_[0]) > 0) {
const uint32 kMax1ByteVarint = 0x7f;
uint32 tag = last_tag_ = buffer_[0];
Advance(1);
- return make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff);
+ return std::make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff);
}
// Other hot case: cutoff >= 0x80, buffer_ has at least two bytes available,
// and tag is two bytes. The latter is tested by bitwise-and-not of the
@@ -937,12 +979,12 @@ inline std::pair<uint32, bool> CodedInputStream::ReadTagWithCutoff(
// so we don't have to check for tag == 0. We may need to check whether
// it exceeds cutoff.
bool at_or_below_cutoff = cutoff >= kMax2ByteVarint || tag <= cutoff;
- return make_pair(tag, at_or_below_cutoff);
+ return std::make_pair(tag, at_or_below_cutoff);
}
}
// Slow path
- last_tag_ = ReadTagFallback();
- return make_pair(last_tag_, static_cast<uint32>(last_tag_ - 1) < cutoff);
+ last_tag_ = ReadTagFallback(first_byte_or_zero);
+ return std::make_pair(last_tag_, static_cast<uint32>(last_tag_ - 1) < cutoff);
}
inline bool CodedInputStream::LastTagWas(uint32 expected) {
@@ -1027,13 +1069,14 @@ inline uint8* CodedOutputStream::GetDirectBufferForNBytesAndAdvance(int size) {
}
inline uint8* CodedOutputStream::WriteVarint32ToArray(uint32 value,
- uint8* target) {
- if (value < 0x80) {
- *target = value;
- return target + 1;
- } else {
- return WriteVarint32FallbackToArray(value, target);
+ uint8* target) {
+ while (value >= 0x80) {
+ *target = static_cast<uint8>(value | 0x80);
+ value >>= 7;
+ ++target;
}
+ *target = static_cast<uint8>(value);
+ return target + 1;
}
inline void CodedOutputStream::WriteVarint32SignExtended(int32 value) {
@@ -1086,22 +1129,26 @@ inline uint8* CodedOutputStream::WriteLittleEndian64ToArray(uint64 value,
return target + sizeof(value);
}
+inline void CodedOutputStream::WriteVarint32(uint32 value) {
+ if (buffer_size_ >= 5) {
+ // Fast path: We have enough bytes left in the buffer to guarantee that
+ // this write won't cross the end, so we can skip the checks.
+ uint8* target = buffer_;
+ uint8* end = WriteVarint32ToArray(value, target);
+ int size = end - target;
+ Advance(size);
+ } else {
+ WriteVarint32SlowPath(value);
+ }
+}
+
inline void CodedOutputStream::WriteTag(uint32 value) {
WriteVarint32(value);
}
inline uint8* CodedOutputStream::WriteTagToArray(
uint32 value, uint8* target) {
- if (value < (1 << 7)) {
- target[0] = value;
- return target + 1;
- } else if (value < (1 << 14)) {
- target[0] = static_cast<uint8>(value | 0x80);
- target[1] = static_cast<uint8>(value >> 7);
- return target + 2;
- } else {
- return WriteVarint32FallbackToArray(value, target);
- }
+ return WriteVarint32ToArray(value, target);
}
inline int CodedOutputStream::VarintSize32(uint32 value) {
@@ -1165,6 +1212,11 @@ inline void CodedInputStream::DecrementRecursionDepth() {
if (recursion_budget_ < recursion_limit_) ++recursion_budget_;
}
+inline void CodedInputStream::UnsafeDecrementRecursionDepth() {
+ assert(recursion_budget_ < recursion_limit_);
+ ++recursion_budget_;
+}
+
inline void CodedInputStream::SetExtensionRegistry(const DescriptorPool* pool,
MessageFactory* factory) {
extension_pool_ = pool;
diff --git a/src/google/protobuf/io/coded_stream_inl.h b/src/google/protobuf/io/coded_stream_inl.h
index cd8d1746..fa20f208 100644
--- a/src/google/protobuf/io/coded_stream_inl.h
+++ b/src/google/protobuf/io/coded_stream_inl.h
@@ -66,6 +66,23 @@ inline bool CodedInputStream::InternalReadStringInline(string* buffer,
return ReadStringFallback(buffer, size);
}
+inline bool CodedInputStream::InternalReadRawInline(void* buffer, int size) {
+ int current_buffer_size;
+ while ((current_buffer_size = BufferSize()) < size) {
+ // Reading past end of buffer. Copy what we have, then refresh.
+ memcpy(buffer, buffer_, current_buffer_size);
+ buffer = reinterpret_cast<uint8*>(buffer) + current_buffer_size;
+ size -= current_buffer_size;
+ Advance(current_buffer_size);
+ if (!Refresh()) return false;
+ }
+
+ memcpy(buffer, buffer_, size);
+ Advance(size);
+
+ return true;
+}
+
} // namespace io
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
index bbe5e399..02d5bad3 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -502,11 +502,11 @@ struct Fixed64Case {
};
inline std::ostream& operator<<(std::ostream& os, const Fixed32Case& c) {
- return os << "0x" << hex << c.value << dec;
+ return os << "0x" << std::hex << c.value << std::dec;
}
inline std::ostream& operator<<(std::ostream& os, const Fixed64Case& c) {
- return os << "0x" << hex << c.value << dec;
+ return os << "0x" << std::hex << c.value << std::dec;
}
Fixed32Case kFixed32Cases[] = {
diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc
index e6037863..dd7c036e 100644
--- a/src/google/protobuf/io/gzip_stream.cc
+++ b/src/google/protobuf/io/gzip_stream.cc
@@ -33,8 +33,6 @@
// This file contains the implementation of classes GzipInputStream and
// GzipOutputStream.
-#include "config.h"
-
#if HAVE_ZLIB
#include <google/protobuf/io/gzip_stream.h>
@@ -49,6 +47,7 @@ static const int kDefaultBufferSize = 65536;
GzipInputStream::GzipInputStream(
ZeroCopyInputStream* sub_stream, Format format, int buffer_size)
: format_(format), sub_stream_(sub_stream), zerror_(Z_OK), byte_count_(0) {
+ zcontext_.state = Z_NULL;
zcontext_.zalloc = Z_NULL;
zcontext_.zfree = Z_NULL;
zcontext_.opaque = Z_NULL;
diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc
index e621ba1d..3ae8c268 100644
--- a/src/google/protobuf/io/printer.cc
+++ b/src/google/protobuf/io/printer.cc
@@ -155,6 +155,78 @@ void Printer::Print(const char* text,
Print(vars, text);
}
+void Printer::Print(const char* text,
+ const char* variable1, const string& value1,
+ const char* variable2, const string& value2,
+ const char* variable3, const string& value3,
+ const char* variable4, const string& value4,
+ const char* variable5, const string& value5) {
+ map<string, string> vars;
+ vars[variable1] = value1;
+ vars[variable2] = value2;
+ vars[variable3] = value3;
+ vars[variable4] = value4;
+ vars[variable5] = value5;
+ Print(vars, text);
+}
+
+void Printer::Print(const char* text,
+ const char* variable1, const string& value1,
+ const char* variable2, const string& value2,
+ const char* variable3, const string& value3,
+ const char* variable4, const string& value4,
+ const char* variable5, const string& value5,
+ const char* variable6, const string& value6) {
+ map<string, string> vars;
+ vars[variable1] = value1;
+ vars[variable2] = value2;
+ vars[variable3] = value3;
+ vars[variable4] = value4;
+ vars[variable5] = value5;
+ vars[variable6] = value6;
+ Print(vars, text);
+}
+
+void Printer::Print(const char* text,
+ const char* variable1, const string& value1,
+ const char* variable2, const string& value2,
+ const char* variable3, const string& value3,
+ const char* variable4, const string& value4,
+ const char* variable5, const string& value5,
+ const char* variable6, const string& value6,
+ const char* variable7, const string& value7) {
+ map<string, string> vars;
+ vars[variable1] = value1;
+ vars[variable2] = value2;
+ vars[variable3] = value3;
+ vars[variable4] = value4;
+ vars[variable5] = value5;
+ vars[variable6] = value6;
+ vars[variable7] = value7;
+ Print(vars, text);
+}
+
+void Printer::Print(const char* text,
+ const char* variable1, const string& value1,
+ const char* variable2, const string& value2,
+ const char* variable3, const string& value3,
+ const char* variable4, const string& value4,
+ const char* variable5, const string& value5,
+ const char* variable6, const string& value6,
+ const char* variable7, const string& value7,
+ const char* variable8, const string& value8) {
+ map<string, string> vars;
+ vars[variable1] = value1;
+ vars[variable2] = value2;
+ vars[variable3] = value3;
+ vars[variable4] = value4;
+ vars[variable5] = value5;
+ vars[variable6] = value6;
+ vars[variable7] = value7;
+ vars[variable8] = value8;
+ Print(vars, text);
+}
+
void Printer::Indent() {
indent_ += " ";
}
diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h
index 92ce3409..f1490bbe 100644
--- a/src/google/protobuf/io/printer.h
+++ b/src/google/protobuf/io/printer.h
@@ -91,8 +91,36 @@ class LIBPROTOBUF_EXPORT Printer {
const char* variable2, const string& value2,
const char* variable3, const string& value3,
const char* variable4, const string& value4);
- // TODO(kenton): Overloaded versions with more variables? Three seems
- // to be enough.
+ // Like the first Print(), except the substitutions are given as parameters.
+ void Print(const char* text, const char* variable1, const string& value1,
+ const char* variable2, const string& value2,
+ const char* variable3, const string& value3,
+ const char* variable4, const string& value4,
+ const char* variable5, const string& value5);
+ // Like the first Print(), except the substitutions are given as parameters.
+ void Print(const char* text, const char* variable1, const string& value1,
+ const char* variable2, const string& value2,
+ const char* variable3, const string& value3,
+ const char* variable4, const string& value4,
+ const char* variable5, const string& value5,
+ const char* variable6, const string& value6);
+ // Like the first Print(), except the substitutions are given as parameters.
+ void Print(const char* text, const char* variable1, const string& value1,
+ const char* variable2, const string& value2,
+ const char* variable3, const string& value3,
+ const char* variable4, const string& value4,
+ const char* variable5, const string& value5,
+ const char* variable6, const string& value6,
+ const char* variable7, const string& value7);
+ // Like the first Print(), except the substitutions are given as parameters.
+ void Print(const char* text, const char* variable1, const string& value1,
+ const char* variable2, const string& value2,
+ const char* variable3, const string& value3,
+ const char* variable4, const string& value4,
+ const char* variable5, const string& value5,
+ const char* variable6, const string& value6,
+ const char* variable7, const string& value7,
+ const char* variable8, const string& value8);
// Indent text by two spaces. After calling Indent(), two spaces will be
// inserted at the beginning of each line of text. Indent() may be called
diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc
index ef2de300..60bd7957 100644
--- a/src/google/protobuf/io/tokenizer.cc
+++ b/src/google/protobuf/io/tokenizer.cc
@@ -762,6 +762,15 @@ bool Tokenizer::NextWithComments(string* prev_trailing_comments,
next_leading_comments);
if (current_.type == TYPE_START) {
+ // Ignore unicode byte order mark(BOM) if it appears at the file
+ // beginning. Only UTF-8 BOM (0xEF 0xBB 0xBF) is accepted.
+ if (TryConsume((char)0xEF)) {
+ if (!TryConsume((char)0xBB) || !TryConsume((char)0xBF)) {
+ AddError("Proto file starts with 0xEF but not UTF-8 BOM. "
+ "Only UTF-8 is accepted for proto file.");
+ return false;
+ }
+ }
collector.DetachFromPrev();
} else {
// A comment appearing on the same line must be attached to the previous
diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
index 3e25edfa..4360b18f 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
@@ -368,7 +368,7 @@ inline char* mutable_string_data(string* s) {
inline std::pair<char*, bool> as_string_data(string* s) {
char *p = mutable_string_data(s);
#ifdef LANG_CXX11
- return make_pair(p, true);
+ return std::make_pair(p, true);
#else
return make_pair(p, p != NULL);
#endif
diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc
index dd3d1285..f2e5b629 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -46,8 +46,6 @@
// "parametized tests" so that one set of tests can be used on all the
// implementations.
-#include "config.h"
-
#ifdef _MSC_VER
#include <io.h>
#else
diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc
index a3705269..5af8b24d 100644
--- a/src/google/protobuf/lite_unittest.cc
+++ b/src/google/protobuf/lite_unittest.cc
@@ -34,12 +34,16 @@
#include <iostream>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arena_test_util.h>
+#include <google/protobuf/map_lite_unittest.pb.h>
+#include <google/protobuf/map_lite_test_util.h>
#include <google/protobuf/test_util_lite.h>
#include <google/protobuf/unittest_lite.pb.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <google/protobuf/wire_format_lite.h>
#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/stubs/strutil.h>
using namespace std;
@@ -84,6 +88,12 @@ void SetSomeTypesInEmptyMessageUnknownFields(
} // namespace
+#define EXPECT_TRUE GOOGLE_CHECK
+#define ASSERT_TRUE GOOGLE_CHECK
+#define EXPECT_FALSE(COND) GOOGLE_CHECK(!(COND))
+#define EXPECT_EQ GOOGLE_CHECK_EQ
+#define ASSERT_EQ GOOGLE_CHECK_EQ
+
int main(int argc, char* argv[]) {
string data, data2, packed_data;
@@ -345,6 +355,374 @@ int main(int argc, char* argv[]) {
GOOGLE_CHECK_EQ(0, empty_message.unknown_fields().size());
}
- cout << "PASS" << endl;
+ // Tests for map lite =============================================
+
+ {
+ // Accessors
+ protobuf_unittest::TestMapLite message;
+
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message);
+
+ google::protobuf::MapLiteTestUtil::ModifyMapFields(&message);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsModified(message);
+ }
+
+ {
+ // SetMapFieldsInitialized
+ protobuf_unittest::TestMapLite message;
+
+ google::protobuf::MapLiteTestUtil::SetMapFieldsInitialized(&message);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSetInitialized(message);
+ }
+
+ {
+ // Proto2SetMapFieldsInitialized
+ protobuf_unittest::TestEnumStartWithNonZeroMapLite message;
+ EXPECT_EQ(protobuf_unittest::PROTO2_NON_ZERO_MAP_ENUM_FOO_LITE,
+ (*message.mutable_map_field())[0]);
+ }
+
+ {
+ // Clear
+ protobuf_unittest::TestMapLite message;
+
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message);
+ message.Clear();
+ google::protobuf::MapLiteTestUtil::ExpectClear(message);
+ }
+
+ {
+ // ClearMessageMap
+ protobuf_unittest::TestMessageMapLite message;
+
+ // Creates a TestAllTypes with default value
+ google::protobuf::TestUtilLite::ExpectClear(
+ (*message.mutable_map_int32_message())[0]);
+ }
+
+ {
+ // CopyFrom
+ protobuf_unittest::TestMapLite message1, message2;
+
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+ message2.CopyFrom(message1);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+
+ // Copying from self should be a no-op.
+ message2.CopyFrom(message2);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+ }
+
+ {
+ // CopyFromMessageMap
+ protobuf_unittest::TestMessageMapLite message1, message2;
+
+ (*message1.mutable_map_int32_message())[0].add_repeated_int32(100);
+ (*message2.mutable_map_int32_message())[0].add_repeated_int32(101);
+
+ message1.CopyFrom(message2);
+
+ // Checks repeated field is overwritten.
+ EXPECT_EQ(1, message1.map_int32_message().at(0).repeated_int32_size());
+ EXPECT_EQ(101, message1.map_int32_message().at(0).repeated_int32(0));
+ }
+
+ {
+ // SwapWithEmpty
+ protobuf_unittest::TestMapLite message1, message2;
+
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message1);
+ google::protobuf::MapLiteTestUtil::ExpectClear(message2);
+
+ message1.Swap(&message2);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+ google::protobuf::MapLiteTestUtil::ExpectClear(message1);
+ }
+
+ {
+ // SwapWithSelf
+ protobuf_unittest::TestMapLite message;
+
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message);
+
+ message.Swap(&message);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message);
+ }
+
+ {
+ // SwapWithOther
+ protobuf_unittest::TestMapLite message1, message2;
+
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message2);
+ google::protobuf::MapLiteTestUtil::ModifyMapFields(&message2);
+
+ message1.Swap(&message2);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsModified(message1);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+ }
+
+ {
+ // CopyConstructor
+ protobuf_unittest::TestMapLite message1;
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+
+ protobuf_unittest::TestMapLite message2(message1);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+ }
+
+ {
+ // CopyAssignmentOperator
+ protobuf_unittest::TestMapLite message1;
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+
+ protobuf_unittest::TestMapLite message2;
+ message2 = message1;
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+
+ // Make sure that self-assignment does something sane.
+ message2.operator=(message2);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+ }
+
+ {
+ // NonEmptyMergeFrom
+ protobuf_unittest::TestMapLite message1, message2;
+
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+
+ // This field will test merging into an empty spot.
+ (*message2.mutable_map_int32_int32())[1] = 1;
+ message1.mutable_map_int32_int32()->erase(1);
+
+ // This tests overwriting.
+ (*message2.mutable_map_int32_double())[1] = 1;
+ (*message1.mutable_map_int32_double())[1] = 2;
+
+ message1.MergeFrom(message2);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message1);
+ }
+
+ {
+ // MergeFromMessageMap
+ protobuf_unittest::TestMessageMapLite message1, message2;
+
+ (*message1.mutable_map_int32_message())[0].add_repeated_int32(100);
+ (*message2.mutable_map_int32_message())[0].add_repeated_int32(101);
+
+ message1.MergeFrom(message2);
+
+ // Checks repeated field is overwritten.
+ EXPECT_EQ(1, message1.map_int32_message().at(0).repeated_int32_size());
+ EXPECT_EQ(101, message1.map_int32_message().at(0).repeated_int32(0));
+ }
+
+ {
+ // Test the generated SerializeWithCachedSizesToArray()
+ protobuf_unittest::TestMapLite message1, message2;
+ string data;
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+ int size = message1.ByteSize();
+ data.resize(size);
+ ::google::protobuf::uint8* start = reinterpret_cast< ::google::protobuf::uint8*>(::google::protobuf::string_as_array(&data));
+ ::google::protobuf::uint8* end = message1.SerializeWithCachedSizesToArray(start);
+ EXPECT_EQ(size, end - start);
+ EXPECT_TRUE(message2.ParseFromString(data));
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+ }
+
+ {
+ // Test the generated SerializeWithCachedSizes()
+ protobuf_unittest::TestMapLite message1, message2;
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+ int size = message1.ByteSize();
+ string data;
+ data.resize(size);
+ {
+ // Allow the output stream to buffer only one byte at a time.
+ google::protobuf::io::ArrayOutputStream array_stream(
+ ::google::protobuf::string_as_array(&data), size, 1);
+ google::protobuf::io::CodedOutputStream output_stream(&array_stream);
+ message1.SerializeWithCachedSizes(&output_stream);
+ EXPECT_FALSE(output_stream.HadError());
+ EXPECT_EQ(size, output_stream.ByteCount());
+ }
+ EXPECT_TRUE(message2.ParseFromString(data));
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+ }
+
+
+ {
+ // Proto2UnknownEnum
+ protobuf_unittest::TestEnumMapPlusExtraLite from;
+ (*from.mutable_known_map_field())[0] =
+ protobuf_unittest::E_PROTO2_MAP_ENUM_FOO_LITE;
+ (*from.mutable_unknown_map_field())[0] =
+ protobuf_unittest::E_PROTO2_MAP_ENUM_EXTRA_LITE;
+ string data;
+ from.SerializeToString(&data);
+
+ protobuf_unittest::TestEnumMapLite to;
+ EXPECT_TRUE(to.ParseFromString(data));
+ EXPECT_EQ(0, to.unknown_map_field().size());
+ EXPECT_FALSE(to.mutable_unknown_fields()->empty());
+ EXPECT_EQ(1, to.known_map_field().size());
+ EXPECT_EQ(protobuf_unittest::PROTO2_MAP_ENUM_FOO_LITE,
+ to.known_map_field().at(0));
+
+ data.clear();
+ from.Clear();
+ to.SerializeToString(&data);
+ EXPECT_TRUE(from.ParseFromString(data));
+ EXPECT_EQ(1, from.known_map_field().size());
+ EXPECT_EQ(protobuf_unittest::E_PROTO2_MAP_ENUM_FOO_LITE,
+ from.known_map_field().at(0));
+ EXPECT_EQ(1, from.unknown_map_field().size());
+ EXPECT_EQ(protobuf_unittest::E_PROTO2_MAP_ENUM_EXTRA_LITE,
+ from.unknown_map_field().at(0));
+ }
+
+ {
+ // StandardWireFormat
+ protobuf_unittest::TestMapLite message;
+ string data = "\x0A\x04\x08\x01\x10\x01";
+
+ EXPECT_TRUE(message.ParseFromString(data));
+ EXPECT_EQ(1, message.map_int32_int32().size());
+ EXPECT_EQ(1, message.map_int32_int32().at(1));
+ }
+
+ {
+ // UnorderedWireFormat
+ protobuf_unittest::TestMapLite message;
+
+ // put value before key in wire format
+ string data = "\x0A\x04\x10\x01\x08\x02";
+
+ EXPECT_TRUE(message.ParseFromString(data));
+ EXPECT_EQ(1, message.map_int32_int32().size());
+ EXPECT_EQ(1, message.map_int32_int32().at(2));
+ }
+
+ {
+ // DuplicatedKeyWireFormat
+ protobuf_unittest::TestMapLite message;
+
+ // Two key fields in wire format
+ string data = "\x0A\x06\x08\x01\x08\x02\x10\x01";
+
+ EXPECT_TRUE(message.ParseFromString(data));
+ EXPECT_EQ(1, message.map_int32_int32().size());
+ EXPECT_EQ(1, message.map_int32_int32().at(2));
+ }
+
+ {
+ // DuplicatedValueWireFormat
+ protobuf_unittest::TestMapLite message;
+
+ // Two value fields in wire format
+ string data = "\x0A\x06\x08\x01\x10\x01\x10\x02";
+
+ EXPECT_TRUE(message.ParseFromString(data));
+ EXPECT_EQ(1, message.map_int32_int32().size());
+ EXPECT_EQ(2, message.map_int32_int32().at(1));
+ }
+
+ {
+ // MissedKeyWireFormat
+ protobuf_unittest::TestMapLite message;
+
+ // No key field in wire format
+ string data = "\x0A\x02\x10\x01";
+
+ EXPECT_TRUE(message.ParseFromString(data));
+ EXPECT_EQ(1, message.map_int32_int32().size());
+ EXPECT_EQ(1, message.map_int32_int32().at(0));
+ }
+
+ {
+ // MissedValueWireFormat
+ protobuf_unittest::TestMapLite message;
+
+ // No value field in wire format
+ string data = "\x0A\x02\x08\x01";
+
+ EXPECT_TRUE(message.ParseFromString(data));
+ EXPECT_EQ(1, message.map_int32_int32().size());
+ EXPECT_EQ(0, message.map_int32_int32().at(1));
+ }
+
+ {
+ // UnknownFieldWireFormat
+ protobuf_unittest::TestMapLite message;
+
+ // Unknown field in wire format
+ string data = "\x0A\x06\x08\x02\x10\x03\x18\x01";
+
+ EXPECT_TRUE(message.ParseFromString(data));
+ EXPECT_EQ(1, message.map_int32_int32().size());
+ EXPECT_EQ(3, message.map_int32_int32().at(2));
+ }
+
+ {
+ // CorruptedWireFormat
+ protobuf_unittest::TestMapLite message;
+
+ // corrupted data in wire format
+ string data = "\x0A\x06\x08\x02\x11\x03";
+
+ EXPECT_FALSE(message.ParseFromString(data));
+ }
+
+ {
+ // IsInitialized
+ protobuf_unittest::TestRequiredMessageMapLite map_message;
+
+ // Add an uninitialized message.
+ (*map_message.mutable_map_field())[0];
+ EXPECT_FALSE(map_message.IsInitialized());
+
+ // Initialize uninitialized message
+ (*map_message.mutable_map_field())[0].set_a(0);
+ (*map_message.mutable_map_field())[0].set_b(0);
+ (*map_message.mutable_map_field())[0].set_c(0);
+ EXPECT_TRUE(map_message.IsInitialized());
+ }
+
+ // arena support for map =========================================
+
+ {
+ // ParsingAndSerializingNoHeapAllocation
+
+ // Allocate a large initial block to avoid mallocs during hooked test.
+ std::vector<char> arena_block(128 * 1024);
+ google::protobuf::ArenaOptions options;
+ options.initial_block = &arena_block[0];
+ options.initial_block_size = arena_block.size();
+ google::protobuf::Arena arena(options);
+ string data;
+ data.reserve(128 * 1024);
+
+ {
+ google::protobuf::internal::NoHeapChecker no_heap;
+
+ protobuf_unittest::TestArenaMapLite* from =
+ google::protobuf::Arena::CreateMessage<protobuf_unittest::TestArenaMapLite>(
+ &arena);
+ google::protobuf::MapLiteTestUtil::SetArenaMapFields(from);
+ from->SerializeToString(&data);
+
+ protobuf_unittest::TestArenaMapLite* to =
+ google::protobuf::Arena::CreateMessage<protobuf_unittest::TestArenaMapLite>(
+ &arena);
+ to->ParseFromString(data);
+ google::protobuf::MapLiteTestUtil::ExpectArenaMapFieldsSet(*to);
+ }
+ }
+
+ std::cout << "PASS" << std::endl;
return 0;
}
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index 6d8a9d03..d928b7a7 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -33,7 +33,10 @@
#include <iterator>
#include <google/protobuf/stubs/hash.h>
+#include <limits> // To support Visual Studio 2008
+#include <google/protobuf/arena.h>
+#include <google/protobuf/generated_enum_util.h>
#include <google/protobuf/map_type_handler.h>
namespace google {
@@ -45,10 +48,12 @@ class Map;
template <typename Enum> struct is_proto_enum;
namespace internal {
-template <typename K, typename V, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-class MapField;
-} // namespace internal
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+class MapFieldLite;
+}
// This is the class for google::protobuf::Map's internal value_type. Instead of using
// std::pair as value_type, we use this class which provides us more control of
@@ -61,23 +66,24 @@ class MapPair {
MapPair(const Key& other_first, const T& other_second)
: first(other_first), second(other_second) {}
-
explicit MapPair(const Key& other_first) : first(other_first), second() {}
-
MapPair(const MapPair& other)
: first(other.first), second(other.second) {}
~MapPair() {}
- // Implicitly convertible to std::pair.
- operator std::pair<const Key, T>() const {
- return std::pair<const Key, T>(first, second);
+ // Implicitly convertible to std::pair of compatible types.
+ template <typename T1, typename T2>
+ operator std::pair<T1, T2>() const {
+ return std::pair<T1, T2>(first, second);
}
const Key first;
T second;
private:
+ typedef void DestructorSkippable_;
+ friend class ::google::protobuf::Arena;
friend class Map<Key, T>;
};
@@ -86,6 +92,7 @@ class MapPair {
// interface directly to visit or change map fields.
template <typename Key, typename T>
class Map {
+ typedef internal::MapCppTypeHandler<Key> KeyTypeHandler;
typedef internal::MapCppTypeHandler<T> ValueTypeHandler;
public:
@@ -100,20 +107,120 @@ class Map {
typedef size_t size_type;
typedef hash<Key> hasher;
-
- Map() : default_enum_value_(0) {}
-
- Map(const Map& other) {
+ typedef equal_to<Key> key_equal;
+
+ Map()
+ : arena_(NULL),
+ allocator_(arena_),
+ elements_(0, hasher(), key_equal(), allocator_),
+ default_enum_value_(0) {}
+ explicit Map(Arena* arena)
+ : arena_(arena),
+ allocator_(arena_),
+ elements_(0, hasher(), key_equal(), allocator_),
+ default_enum_value_(0) {}
+
+ Map(const Map& other)
+ : arena_(NULL),
+ allocator_(arena_),
+ elements_(0, hasher(), key_equal(), allocator_),
+ default_enum_value_(other.default_enum_value_) {
insert(other.begin(), other.end());
}
~Map() { clear(); }
+ private:
+ // re-implement std::allocator to use arena allocator for memory allocation.
+ // Used for google::protobuf::Map implementation. Users should not use this class
+ // directly.
+ template <typename U>
+ class MapAllocator {
+ public:
+ typedef U value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ MapAllocator() : arena_(NULL) {}
+ explicit MapAllocator(Arena* arena) : arena_(arena) {}
+ template <typename X>
+ MapAllocator(const MapAllocator<X>& allocator)
+ : arena_(allocator.arena_) {}
+
+ pointer allocate(size_type n, const_pointer hint = 0) {
+ // If arena is not given, malloc needs to be called which doesn't
+ // construct element object.
+ if (arena_ == NULL) {
+ return reinterpret_cast<pointer>(malloc(n * sizeof(value_type)));
+ } else {
+ return reinterpret_cast<pointer>(
+ Arena::CreateArray<uint8>(arena_, n * sizeof(value_type)));
+ }
+ }
+
+ void deallocate(pointer p, size_type n) {
+ if (arena_ == NULL) {
+ free(p);
+ }
+ }
+
+#if __cplusplus >= 201103L && !defined(GOOGLE_PROTOBUF_OS_APPLE) && \
+ !defined(GOOGLE_PROTOBUF_OS_NACL) && !defined(GOOGLE_PROTOBUF_OS_ANDROID)
+ template<class NodeType, class... Args>
+ void construct(NodeType* p, Args&&... args) {
+ new ((void*)p) NodeType(std::forward<Args>(args)...);
+ }
+
+ template<class NodeType>
+ void destroy(NodeType* p) {
+ p->~NodeType();
+ }
+#else
+ void construct(pointer p, const_reference t) { new (p) value_type(t); }
+
+ void destroy(pointer p) { p->~value_type(); }
+#endif
+
+ template <typename X>
+ struct rebind {
+ typedef MapAllocator<X> other;
+ };
+
+ template <typename X>
+ bool operator==(const MapAllocator<X>& other) const {
+ return arena_ == other.arena_;
+ }
+
+ template <typename X>
+ bool operator!=(const MapAllocator<X>& other) const {
+ return arena_ != other.arena_;
+ }
+
+ // To support Visual Studio 2008
+ size_type max_size() const {
+ return std::numeric_limits<size_type>::max();
+ }
+
+ private:
+ Arena* arena_;
+
+ template <typename X>
+ friend class MapAllocator;
+ };
+
+ public:
+ typedef MapAllocator<std::pair<const Key, MapPair<Key, T>*> > Allocator;
+
// Iterators
class const_iterator
: public std::iterator<std::forward_iterator_tag, value_type, ptrdiff_t,
const value_type*, const value_type&> {
- typedef typename hash_map<Key, value_type*>::const_iterator InnerIt;
+ typedef typename hash_map<Key, value_type*, hash<Key>, equal_to<Key>,
+ Allocator>::const_iterator InnerIt;
public:
const_iterator() {}
@@ -140,7 +247,8 @@ class Map {
};
class iterator : public std::iterator<std::forward_iterator_tag, value_type> {
- typedef typename hash_map<Key, value_type*>::iterator InnerIt;
+ typedef typename hash_map<Key, value_type*, hasher, equal_to<Key>,
+ Allocator>::iterator InnerIt;
public:
iterator() {}
@@ -185,7 +293,7 @@ class Map {
T& operator[](const key_type& key) {
value_type** value = &elements_[key];
if (*value == NULL) {
- *value = new value_type(key);
+ *value = CreateValueTypeInternal(key);
internal::MapValueInitializer<google::protobuf::is_proto_enum<T>::value,
T>::Initialize((*value)->second,
default_enum_value_);
@@ -241,7 +349,7 @@ class Map {
} else {
return std::pair<iterator, bool>(
iterator(elements_.insert(std::pair<Key, value_type*>(
- value.first, new value_type(value))).first), true);
+ value.first, CreateValueTypeInternal(value))).first), true);
}
}
template <class InputIt>
@@ -256,28 +364,29 @@ class Map {
// Erase
size_type erase(const key_type& key) {
- typename hash_map<Key, value_type*>::iterator it = elements_.find(key);
+ typename hash_map<Key, value_type*, hash<Key>, equal_to<Key>,
+ Allocator>::iterator it = elements_.find(key);
if (it == elements_.end()) {
return 0;
} else {
- delete it->second;
+ if (arena_ == NULL) delete it->second;
elements_.erase(it);
return 1;
}
}
void erase(iterator pos) {
- delete pos.it_->second;
+ if (arena_ == NULL) delete pos.it_->second;
elements_.erase(pos.it_);
}
void erase(iterator first, iterator last) {
for (iterator it = first; it != last;) {
- delete it.it_->second;
+ if (arena_ == NULL) delete it.it_->second;
elements_.erase((it++).it_);
}
}
void clear() {
for (iterator it = begin(); it != end(); ++it) {
- delete it.it_->second;
+ if (arena_ == NULL) delete it.it_->second;
}
elements_.clear();
}
@@ -297,12 +406,46 @@ class Map {
default_enum_value_ = default_enum_value;
}
- hash_map<Key, value_type*> elements_;
+ value_type* CreateValueTypeInternal(const Key& key) {
+ if (arena_ == NULL) {
+ return new value_type(key);
+ } else {
+ value_type* value = reinterpret_cast<value_type*>(
+ Arena::CreateArray<uint8>(arena_, sizeof(value_type)));
+ Arena::CreateInArenaStorage(const_cast<Key*>(&value->first), arena_);
+ Arena::CreateInArenaStorage(&value->second, arena_);
+ const_cast<Key&>(value->first) = key;
+ return value;
+ }
+ }
+
+ value_type* CreateValueTypeInternal(const value_type& value) {
+ if (arena_ == NULL) {
+ return new value_type(value);
+ } else {
+ value_type* p = reinterpret_cast<value_type*>(
+ Arena::CreateArray<uint8>(arena_, sizeof(value_type)));
+ Arena::CreateInArenaStorage(const_cast<Key*>(&p->first), arena_);
+ Arena::CreateInArenaStorage(&p->second, arena_);
+ const_cast<Key&>(p->first) = value.first;
+ p->second = value.second;
+ return p;
+ }
+ }
+
+ Arena* arena_;
+ Allocator allocator_;
+ hash_map<Key, value_type*, hash<Key>, equal_to<Key>, Allocator> elements_;
int default_enum_value_;
- template <typename K, typename V, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum>
- friend class internal::MapField;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
+ template <typename K, typename V,
+ internal::WireFormatLite::FieldType key_wire_type,
+ internal::WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+ friend class internal::MapFieldLite;
};
} // namespace protobuf
diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h
index 217b15f6..e93d0348 100644
--- a/src/google/protobuf/map_entry.h
+++ b/src/google/protobuf/map_entry.h
@@ -31,13 +31,23 @@
#ifndef GOOGLE_PROTOBUF_MAP_ENTRY_H__
#define GOOGLE_PROTOBUF_MAP_ENTRY_H__
-#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/map_entry_lite.h>
#include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/wire_format_lite_inl.h>
namespace google {
namespace protobuf {
class Arena;
+namespace internal {
+template <typename Key, typename Value,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+class MapField;
+}
}
namespace protobuf {
@@ -45,7 +55,8 @@ namespace internal {
// Register all MapEntry default instances so we can delete them in
// ShutdownProtobufLibrary().
-void LIBPROTOBUF_EXPORT RegisterMapEntryDefaultInstance(MessageLite* default_instance);
+void LIBPROTOBUF_EXPORT RegisterMapEntryDefaultInstance(
+ MessageLite* default_instance);
// This is the common base class for MapEntry. It is used by MapFieldBase in
// reflection api, in which the static type of key and value is unknown.
@@ -82,179 +93,103 @@ class LIBPROTOBUF_EXPORT MapEntryBase : public Message {
// while we need to explicitly tell cpp type if proto type is TYPE_MESSAGE to
// get internal layout.
// Moreover, default_enum_value is used to initialize enum field in proto2.
-template <typename Key, typename Value, FieldDescriptor::Type KeyProtoType,
- FieldDescriptor::Type ValueProtoType, int default_enum_value>
+template <typename Key, typename Value,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
class MapEntry : public MapEntryBase {
- // Handlers for key/value's proto field type. Used to infer internal layout
- // and provide parsing/serialization support.
- typedef MapProtoTypeHandler<KeyProtoType> KeyProtoHandler;
- typedef MapProtoTypeHandler<ValueProtoType> ValueProtoHandler;
+ // Handlers for key/value wire type. Provide utilities to parse/serialize
+ // key/value.
+ typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler;
+ typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler;
// Define key/value's internal stored type. Message is the only one whose
// internal stored type cannot be inferred from its proto type.
- typedef typename KeyProtoHandler::CppType KeyProtoHandlerCppType;
- typedef typename ValueProtoHandler::CppType ValueProtoHandlerCppType;
- static const bool kIsKeyMessage = KeyProtoHandler::kIsMessage;
- static const bool kIsValueMessage = ValueProtoHandler::kIsMessage;
- typedef typename MapIf<kIsKeyMessage, Key, KeyProtoHandlerCppType>::type
+ static const bool kIsKeyMessage = KeyWireHandler::kIsMessage;
+ static const bool kIsValueMessage = ValueWireHandler::kIsMessage;
+ typedef typename KeyWireHandler::CppType KeyInternalType;
+ typedef typename ValueWireHandler::CppType ValueInternalType;
+ typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type
KeyCppType;
- typedef typename MapIf<kIsValueMessage, Value, ValueProtoHandlerCppType>::type
+ typedef typename MapIf<kIsValueMessage, Value, ValueInternalType>::type
ValCppType;
- // Handlers for key/value's internal stored type. Provide utilities to
- // manipulate internal stored type. We need it because some types are stored
- // as values and others are stored as pointers (Message and string), but we
- // need to keep the code in MapEntry unified instead of providing different
- // codes for each type.
- typedef MapCppTypeHandler<KeyCppType> KeyCppHandler;
- typedef MapCppTypeHandler<ValCppType> ValueCppHandler;
-
- // Define internal memory layout. Strings and messages are stored as
- // pointers, while other types are stored as values.
- static const bool kKeyIsStringOrMessage = KeyCppHandler::kIsStringOrMessage;
- static const bool kValIsStringOrMessage = ValueCppHandler::kIsStringOrMessage;
- typedef typename MapIf<kKeyIsStringOrMessage, KeyCppType*, KeyCppType>::type
- KeyBase;
- typedef typename MapIf<kValIsStringOrMessage, ValCppType*, ValCppType>::type
- ValueBase;
-
// Abbreviation for MapEntry
typedef typename google::protobuf::internal::MapEntry<
- Key, Value, KeyProtoType, ValueProtoType, default_enum_value> EntryType;
-
- // Constants for field number.
- static const int kKeyFieldNumber = 1;
- static const int kValueFieldNumber = 2;
+ Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> EntryType;
- // Constants for field tag.
- static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
- kKeyFieldNumber, KeyProtoHandler::kWireType);
- static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
- kValueFieldNumber, ValueProtoHandler::kWireType);
- static const int kTagSize = 1;
+ // Abbreviation for MapEntryLite
+ typedef typename google::protobuf::internal::MapEntryLite<
+ Key, Value, kKeyFieldType, kValueFieldType, default_enum_value>
+ EntryLiteType;
public:
~MapEntry() {
if (this == default_instance_) {
delete reflection_;
- } else {
- KeyCppHandler::Delete(key_);
- ValueCppHandler::Delete(value_);
}
}
// accessors ======================================================
- inline void set_key(const KeyCppType& key) {
- KeyCppHandler::EnsureMutable(&key_);
- KeyCppHandler::Merge(key, &key_);
- set_has_key();
- }
virtual inline const KeyCppType& key() const {
- return KeyCppHandler::Reference(key_);
+ return entry_lite_.key();
}
inline KeyCppType* mutable_key() {
- set_has_key();
- KeyCppHandler::EnsureMutable(&key_);
- return KeyCppHandler::Pointer(key_);
- }
- inline void set_value(const ValCppType& value) {
- ValueCppHandler::EnsureMutable(&value_);
- ValueCppHandler::Merge(value, &value_);
- set_has_value();
+ return entry_lite_.mutable_key();
}
virtual inline const ValCppType& value() const {
- GOOGLE_CHECK(default_instance_ != NULL);
- return ValueCppHandler::DefaultIfNotInitialized(value_,
- default_instance_->value_);
+ return entry_lite_.value();
}
inline ValCppType* mutable_value() {
- set_has_value();
- ValueCppHandler::EnsureMutable(&value_);
- return ValueCppHandler::Pointer(value_);
+ return entry_lite_.mutable_value();
}
// implements Message =============================================
bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
- uint32 tag;
-
- for (;;) {
- // 1) corrupted data: return false;
- // 2) unknown field: skip without putting into unknown field set;
- // 3) unknown enum value: keep it in parsing. In proto2, caller should
- // check the value and put this entry into containing message's unknown
- // field set if the value is an unknown enum. In proto3, caller doesn't
- // need to care whether the value is unknown enum;
- // 4) missing key/value: missed key/value will have default value. caller
- // should take this entry as if key/value is set to default value.
- tag = input->ReadTag();
- switch (tag) {
- case kKeyTag:
- if (!KeyProtoHandler::Read(input, mutable_key())) return false;
- set_has_key();
- if (!input->ExpectTag(kValueTag)) break;
- GOOGLE_FALLTHROUGH_INTENDED;
-
- case kValueTag:
- if (!ValueProtoHandler::Read(input, mutable_value())) return false;
- set_has_value();
- if (input->ExpectAtEnd()) return true;
- break;
-
- default:
- if (tag == 0 ||
- WireFormatLite::GetTagWireType(tag) ==
- WireFormatLite::WIRETYPE_END_GROUP) {
- return true;
- }
- if (!WireFormatLite::SkipField(input, tag)) return false;
- break;
- }
- }
+ return entry_lite_.MergePartialFromCodedStream(input);
}
int ByteSize() const {
- int size = 0;
- size += has_key() ? kTagSize + KeyProtoHandler::ByteSize(key()) : 0;
- size += has_value() ? kTagSize + ValueProtoHandler::ByteSize(value()) : 0;
- return size;
+ return entry_lite_.ByteSize();
}
void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
- KeyProtoHandler::Write(kKeyFieldNumber, key(), output);
- ValueProtoHandler::Write(kValueFieldNumber, value(), output);
+ entry_lite_.SerializeWithCachedSizes(output);
}
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
- output = KeyProtoHandler::WriteToArray(kKeyFieldNumber, key(), output);
- output =
- ValueProtoHandler::WriteToArray(kValueFieldNumber, value(), output);
- return output;
+ return entry_lite_.SerializeWithCachedSizesToArray(output);
}
int GetCachedSize() const {
- int size = 0;
- size += has_key() ? kTagSize + KeyProtoHandler::GetCachedSize(key()) : 0;
- size +=
- has_value() ? kTagSize + ValueProtoHandler::GetCachedSize(value()) : 0;
- return size;
+ return entry_lite_.GetCachedSize();
}
- bool IsInitialized() const { return ValueCppHandler::IsInitialized(value_); }
+ bool IsInitialized() const {
+ return entry_lite_.IsInitialized();
+ }
Message* New() const {
MapEntry* entry = new MapEntry;
entry->descriptor_ = descriptor_;
entry->reflection_ = reflection_;
- entry->default_instance_ = default_instance_;
+ entry->set_default_instance(default_instance_);
+ return entry;
+ }
+
+ Message* New(Arena* arena) const {
+ MapEntry* entry = Arena::CreateMessage<MapEntry>(arena);
+ entry->descriptor_ = descriptor_;
+ entry->reflection_ = reflection_;
+ entry->set_default_instance(default_instance_);
return entry;
}
int SpaceUsed() const {
int size = sizeof(MapEntry);
- size += KeyCppHandler::SpaceUsedInMapEntry(key_);
- size += ValueCppHandler::SpaceUsedInMapEntry(value_);
+ size += entry_lite_.SpaceUsed();
return size;
}
@@ -279,30 +214,19 @@ class MapEntry : public MapEntryBase {
}
void MergeFrom(const MapEntry& from) {
- if (from._has_bits_[0]) {
- if (from.has_key()) {
- KeyCppHandler::EnsureMutable(&key_);
- KeyCppHandler::Merge(from.key(), &key_);
- set_has_key();
- }
- if (from.has_value()) {
- ValueCppHandler::EnsureMutable(&value_);
- ValueCppHandler::Merge(from.value(), &value_);
- set_has_value();
- }
- }
+ entry_lite_.MergeFrom(from.entry_lite_);
}
void Clear() {
- KeyCppHandler::Clear(&key_);
- ValueCppHandler::ClearMaybeByDefaultEnum(&value_, default_enum_value);
- clear_has_key();
- clear_has_value();
+ entry_lite_.Clear();
}
void InitAsDefaultInstance() {
- KeyCppHandler::AssignDefaultValue(&key_);
- ValueCppHandler::AssignDefaultValue(&value_);
+ entry_lite_.InitAsDefaultInstance();
+ }
+
+ Arena* GetArena() const {
+ return entry_lite_.GetArena();
}
// Create default MapEntry instance for given descriptor. Descriptor has to be
@@ -310,141 +234,58 @@ class MapEntry : public MapEntryBase {
// may have the same type and MapEntry class. The given descriptor is needed
// to distinguish instances of the same MapEntry class.
static MapEntry* CreateDefaultInstance(const Descriptor* descriptor) {
- MapEntry* entry = new MapEntry();
+ MapEntry* entry = new MapEntry;
const Reflection* reflection = new GeneratedMessageReflection(
descriptor, entry, offsets_,
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _has_bits_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_._has_bits_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _unknown_fields_), -1,
DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(), sizeof(MapEntry), -1);
entry->descriptor_ = descriptor;
entry->reflection_ = reflection;
- entry->default_instance_ = entry;
+ entry->set_default_instance(entry);
entry->InitAsDefaultInstance();
RegisterMapEntryDefaultInstance(entry);
return entry;
}
- // Create a MapEntry for given key and value from google::protobuf::Map in
- // serialization. This function is only called when value is enum. Enum is
- // treated differently because its type in MapEntry is int and its type in
- // google::protobuf::Map is enum. We cannot create a reference to int from an enum.
- static MapEntry* EnumWrap(const Key& key, const Value value) {
- return new MapEnumEntryWrapper<Key, Value, KeyProtoType, ValueProtoType,
- default_enum_value>(key, value);
- }
+ private:
+ MapEntry() : default_instance_(NULL), entry_lite_() {}
- // Like above, but for all the other types. This avoids value copy to create
- // MapEntry from google::protobuf::Map in serialization.
- static MapEntry* Wrap(const Key& key, const Value& value) {
- return new MapEntryWrapper<Key, Value, KeyProtoType, ValueProtoType,
- default_enum_value>(key, value);
- }
+ explicit MapEntry(Arena* arena)
+ : default_instance_(NULL), entry_lite_(arena) {}
- protected:
- void set_has_key() { _has_bits_[0] |= 0x00000001u; }
- bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
- void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
- void set_has_value() { _has_bits_[0] |= 0x00000002u; }
- bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
- void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
+ inline Arena* GetArenaNoVirtual() const {
+ return entry_lite_.GetArenaNoVirtual();
+ }
- private:
- // Serializing a generated message containing map field involves serializing
- // key-value pairs from google::protobuf::Map. The wire format of each key-value pair
- // after serialization should be the same as that of a MapEntry message
- // containing the same key and value inside it. However, google::protobuf::Map doesn't
- // store key and value as MapEntry message, which disables us to use existing
- // code to serialize message. In order to use existing code to serialize
- // message, we need to construct a MapEntry from key-value pair. But it
- // involves copy of key and value to construct a MapEntry. In order to avoid
- // this copy in constructing a MapEntry, we need the following class which
- // only takes references of given key and value.
- template <typename KeyNested, typename ValueNested,
- FieldDescriptor::Type KeyProtoNested,
- FieldDescriptor::Type ValueProtoNested, int default_enum>
- class MapEntryWrapper
- : public MapEntry<KeyNested, ValueNested, KeyProtoNested,
- ValueProtoNested, default_enum> {
- typedef MapEntry<KeyNested, ValueNested, KeyProtoNested, ValueProtoNested,
- default_enum_value> Base;
- typedef typename Base::KeyCppType KeyCppType;
- typedef typename Base::ValCppType ValCppType;
-
- public:
- MapEntryWrapper(const KeyNested& key, const ValueNested& value)
- : key_(key), value_(value) {
- Base::set_has_key();
- Base::set_has_value();
- }
- inline const KeyCppType& key() const { return key_; }
- inline const ValCppType& value() const { return value_; }
-
- private:
- const Key& key_;
- const Value& value_;
- };
-
- // Like above, but for enum value only, which stores value instead of
- // reference of value field inside. This is needed because the type of value
- // field in constructor is an enum, while we need to store it as an int. If we
- // initialize a reference to int with a reference to enum, compiler will
- // generate a temporary int from enum and initialize the reference to int with
- // the temporary.
- template <typename KeyNested, typename ValueNested,
- FieldDescriptor::Type KeyProtoNested,
- FieldDescriptor::Type ValueProtoNested, int default_enum>
- class MapEnumEntryWrapper
- : public MapEntry<KeyNested, ValueNested, KeyProtoNested,
- ValueProtoNested, default_enum> {
- typedef MapEntry<KeyNested, ValueNested, KeyProtoNested, ValueProtoNested,
- default_enum> Base;
- typedef typename Base::KeyCppType KeyCppType;
- typedef typename Base::ValCppType ValCppType;
-
- public:
- MapEnumEntryWrapper(const KeyNested& key, const ValueNested& value)
- : key_(key), value_(value) {
- Base::set_has_key();
- Base::set_has_value();
- }
- inline const KeyCppType& key() const { return key_; }
- inline const ValCppType& value() const { return value_; }
-
- private:
- const KeyCppType& key_;
- const ValCppType value_;
- };
-
- MapEntry() : default_instance_(NULL) {
- KeyCppHandler::Initialize(&key_);
- ValueCppHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value);
- _has_bits_[0] = 0;
+ void set_default_instance(MapEntry* default_instance) {
+ default_instance_ = default_instance;
+ entry_lite_.set_default_instance(&default_instance->entry_lite_);
}
- KeyBase key_;
- ValueBase value_;
static int offsets_[2];
UnknownFieldSet _unknown_fields_;
- uint32 _has_bits_[1];
MapEntry* default_instance_;
+ EntryLiteType entry_lite_;
friend class ::google::protobuf::Arena;
- template <typename K, typename V,
- FieldDescriptor::Type KType,
- FieldDescriptor::Type VType, int default_enum>
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
+ template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
+ WireFormatLite::FieldType, int default_enum>
friend class internal::MapField;
- friend class LIBPROTOBUF_EXPORT internal::GeneratedMessageReflection;
+ friend class internal::GeneratedMessageReflection;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry);
};
-template <typename Key, typename Value, FieldDescriptor::Type KeyProtoType,
- FieldDescriptor::Type ValueProtoType, int default_enum_value>
-int MapEntry<Key, Value, KeyProtoType, ValueProtoType,
+template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType, int default_enum_value>
+int MapEntry<Key, Value, kKeyFieldType, kValueFieldType,
default_enum_value>::offsets_[2] = {
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, key_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, value_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.key_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.value_),
};
} // namespace internal
diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h
new file mode 100644
index 00000000..52746da5
--- /dev/null
+++ b/src/google/protobuf/map_entry_lite.h
@@ -0,0 +1,411 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
+#define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
+
+#include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+
+namespace google {
+namespace protobuf {
+class Arena;
+namespace internal {
+template <typename Key, typename Value,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+class MapEntry;
+template <typename Key, typename Value,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+class MapFieldLite;
+} // namespace internal
+} // namespace protobuf
+
+namespace protobuf {
+namespace internal {
+
+// MapEntryLite is used to implement parsing and serialization of map for lite
+// runtime.
+template <typename Key, typename Value,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+class MapEntryLite : public MessageLite {
+ // Handlers for key/value wire type. Provide utilities to parse/serialize
+ // key/value.
+ typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler;
+ typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler;
+
+ // Define key/value's internal stored type. Message is the only one whose
+ // internal stored type cannot be inferred from its proto type
+ static const bool kIsKeyMessage = KeyWireHandler::kIsMessage;
+ static const bool kIsValueMessage = ValueWireHandler::kIsMessage;
+ typedef typename KeyWireHandler::CppType KeyInternalType;
+ typedef typename ValueWireHandler::CppType ValueInternalType;
+ typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type
+ KeyCppType;
+ typedef typename MapIf<kIsValueMessage, Value, ValueInternalType>::type
+ ValCppType;
+
+ // Handlers for key/value's internal stored type. Provide utilities to
+ // manipulate internal stored type. We need it because some types are stored
+ // as values and others are stored as pointers (Message and string), but we
+ // need to keep the code in MapEntry unified instead of providing different
+ // codes for each type.
+ typedef MapCppTypeHandler<KeyCppType> KeyCppHandler;
+ typedef MapCppTypeHandler<ValCppType> ValueCppHandler;
+
+ // Define internal memory layout. Strings and messages are stored as
+ // pointers, while other types are stored as values.
+ static const bool kKeyIsStringOrMessage = KeyCppHandler::kIsStringOrMessage;
+ static const bool kValIsStringOrMessage = ValueCppHandler::kIsStringOrMessage;
+ typedef typename MapIf<kKeyIsStringOrMessage, KeyCppType*, KeyCppType>::type
+ KeyBase;
+ typedef typename MapIf<kValIsStringOrMessage, ValCppType*, ValCppType>::type
+ ValueBase;
+
+ // Constants for field number.
+ static const int kKeyFieldNumber = 1;
+ static const int kValueFieldNumber = 2;
+
+ // Constants for field tag.
+ static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
+ kKeyFieldNumber, KeyWireHandler::kWireType);
+ static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
+ kValueFieldNumber, ValueWireHandler::kWireType);
+ static const int kTagSize = 1;
+
+ public:
+ ~MapEntryLite() {
+ if (this != default_instance_) {
+ KeyCppHandler::Delete(key_);
+ ValueCppHandler::Delete(value_);
+ }
+ }
+
+ // accessors ======================================================
+
+ virtual inline const KeyCppType& key() const {
+ return KeyCppHandler::Reference(key_);
+ }
+ inline KeyCppType* mutable_key() {
+ set_has_key();
+ KeyCppHandler::EnsureMutable(&key_, GetArenaNoVirtual());
+ return KeyCppHandler::Pointer(key_);
+ }
+ virtual inline const ValCppType& value() const {
+ GOOGLE_CHECK(default_instance_ != NULL);
+ return ValueCppHandler::DefaultIfNotInitialized(value_,
+ default_instance_->value_);
+ }
+ inline ValCppType* mutable_value() {
+ set_has_value();
+ ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual());
+ return ValueCppHandler::Pointer(value_);
+ }
+
+ // implements MessageLite =========================================
+
+ // MapEntryLite is for implementation only and this function isn't called
+ // anywhere. Just provide a fake implementation here for MessageLite.
+ string GetTypeName() const { return ""; }
+
+ void CheckTypeAndMergeFrom(const MessageLite& other) {
+ MergeFrom(*::google::protobuf::down_cast<const MapEntryLite*>(&other));
+ }
+
+ bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
+ uint32 tag;
+
+ for (;;) {
+ // 1) corrupted data: return false;
+ // 2) unknown field: skip without putting into unknown field set;
+ // 3) unknown enum value: keep it in parsing. In proto2, caller should
+ // check the value and put this entry into containing message's unknown
+ // field set if the value is an unknown enum. In proto3, caller doesn't
+ // need to care whether the value is unknown enum;
+ // 4) missing key/value: missed key/value will have default value. caller
+ // should take this entry as if key/value is set to default value.
+ tag = input->ReadTag();
+ switch (tag) {
+ case kKeyTag:
+ if (!KeyWireHandler::Read(input, mutable_key())) return false;
+ set_has_key();
+ if (!input->ExpectTag(kValueTag)) break;
+ GOOGLE_FALLTHROUGH_INTENDED;
+
+ case kValueTag:
+ if (!ValueWireHandler::Read(input, mutable_value())) return false;
+ set_has_value();
+ if (input->ExpectAtEnd()) return true;
+ break;
+
+ default:
+ if (tag == 0 ||
+ WireFormatLite::GetTagWireType(tag) ==
+ WireFormatLite::WIRETYPE_END_GROUP) {
+ return true;
+ }
+ if (!WireFormatLite::SkipField(input, tag)) return false;
+ break;
+ }
+ }
+ }
+
+ int ByteSize() const {
+ int size = 0;
+ size += has_key() ? kTagSize + KeyWireHandler::ByteSize(key()) : 0;
+ size += has_value() ? kTagSize + ValueWireHandler::ByteSize(value()) : 0;
+ return size;
+ }
+
+ void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
+ KeyWireHandler::Write(kKeyFieldNumber, key(), output);
+ ValueWireHandler::Write(kValueFieldNumber, value(), output);
+ }
+
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
+ output = KeyWireHandler::WriteToArray(kKeyFieldNumber, key(), output);
+ output =
+ ValueWireHandler::WriteToArray(kValueFieldNumber, value(), output);
+ return output;
+ }
+
+ int GetCachedSize() const {
+ int size = 0;
+ size += has_key() ? kTagSize + KeyWireHandler::GetCachedSize(key()) : 0;
+ size +=
+ has_value() ? kTagSize + ValueWireHandler::GetCachedSize(value()) : 0;
+ return size;
+ }
+
+ bool IsInitialized() const { return ValueCppHandler::IsInitialized(value_); }
+
+ MessageLite* New() const {
+ MapEntryLite* entry = new MapEntryLite;
+ entry->default_instance_ = default_instance_;
+ return entry;
+ }
+
+ MessageLite* New(Arena* arena) const {
+ MapEntryLite* entry = Arena::CreateMessage<MapEntryLite>(arena);
+ entry->default_instance_ = default_instance_;
+ return entry;
+ }
+
+ int SpaceUsed() const {
+ int size = sizeof(MapEntryLite);
+ size += KeyCppHandler::SpaceUsedInMapEntry(key_);
+ size += ValueCppHandler::SpaceUsedInMapEntry(value_);
+ return size;
+ }
+
+ void MergeFrom(const MapEntryLite& from) {
+ if (from._has_bits_[0]) {
+ if (from.has_key()) {
+ KeyCppHandler::EnsureMutable(&key_, GetArenaNoVirtual());
+ KeyCppHandler::Merge(from.key(), &key_);
+ set_has_key();
+ }
+ if (from.has_value()) {
+ ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual());
+ ValueCppHandler::Merge(from.value(), &value_);
+ set_has_value();
+ }
+ }
+ }
+
+ void Clear() {
+ KeyCppHandler::Clear(&key_);
+ ValueCppHandler::ClearMaybeByDefaultEnum(&value_, default_enum_value);
+ clear_has_key();
+ clear_has_value();
+ }
+
+ void InitAsDefaultInstance() {
+ KeyCppHandler::AssignDefaultValue(&key_);
+ ValueCppHandler::AssignDefaultValue(&value_);
+ }
+
+ Arena* GetArena() const {
+ return GetArenaNoVirtual();
+ }
+
+ // Create a MapEntryLite for given key and value from google::protobuf::Map in
+ // serialization. This function is only called when value is enum. Enum is
+ // treated differently because its type in MapEntry is int and its type in
+ // google::protobuf::Map is enum. We cannot create a reference to int from an enum.
+ static MapEntryLite* EnumWrap(const Key& key, const Value value,
+ Arena* arena) {
+ return Arena::CreateMessage<MapEnumEntryWrapper<
+ Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> >(
+ arena, key, value);
+ }
+
+ // Like above, but for all the other types. This avoids value copy to create
+ // MapEntryLite from google::protobuf::Map in serialization.
+ static MapEntryLite* Wrap(const Key& key, const Value& value, Arena* arena) {
+ return Arena::CreateMessage<MapEntryWrapper<Key, Value, kKeyFieldType,
+ kValueFieldType,
+ default_enum_value> >(
+ arena, key, value);
+ }
+
+ protected:
+ void set_has_key() { _has_bits_[0] |= 0x00000001u; }
+ bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
+ void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
+ void set_has_value() { _has_bits_[0] |= 0x00000002u; }
+ bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
+ void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
+
+ private:
+ // Serializing a generated message containing map field involves serializing
+ // key-value pairs from google::protobuf::Map. The wire format of each key-value pair
+ // after serialization should be the same as that of a MapEntry message
+ // containing the same key and value inside it. However, google::protobuf::Map doesn't
+ // store key and value as MapEntry message, which disables us to use existing
+ // code to serialize message. In order to use existing code to serialize
+ // message, we need to construct a MapEntry from key-value pair. But it
+ // involves copy of key and value to construct a MapEntry. In order to avoid
+ // this copy in constructing a MapEntry, we need the following class which
+ // only takes references of given key and value.
+ template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
+ WireFormatLite::FieldType v_wire_type, int default_enum>
+ class MapEntryWrapper
+ : public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> {
+ typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base;
+ typedef typename Base::KeyCppType KeyCppType;
+ typedef typename Base::ValCppType ValCppType;
+
+ public:
+ MapEntryWrapper(Arena* arena, const K& key, const V& value)
+ : MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena),
+ key_(key),
+ value_(value) {
+ Base::set_has_key();
+ Base::set_has_value();
+ }
+ inline const KeyCppType& key() const { return key_; }
+ inline const ValCppType& value() const { return value_; }
+
+ private:
+ const Key& key_;
+ const Value& value_;
+
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
+ };
+
+ // Like above, but for enum value only, which stores value instead of
+ // reference of value field inside. This is needed because the type of value
+ // field in constructor is an enum, while we need to store it as an int. If we
+ // initialize a reference to int with a reference to enum, compiler will
+ // generate a temporary int from enum and initialize the reference to int with
+ // the temporary.
+ template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
+ WireFormatLite::FieldType v_wire_type, int default_enum>
+ class MapEnumEntryWrapper
+ : public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> {
+ typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base;
+ typedef typename Base::KeyCppType KeyCppType;
+ typedef typename Base::ValCppType ValCppType;
+
+ public:
+ MapEnumEntryWrapper(Arena* arena, const K& key, const V& value)
+ : MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena),
+ key_(key),
+ value_(value) {
+ Base::set_has_key();
+ Base::set_has_value();
+ }
+ inline const KeyCppType& key() const { return key_; }
+ inline const ValCppType& value() const { return value_; }
+
+ private:
+ const KeyCppType& key_;
+ const ValCppType value_;
+
+ friend class google::protobuf::Arena;
+ typedef void DestructorSkippable_;
+ };
+
+ MapEntryLite() : default_instance_(NULL), arena_(NULL) {
+ KeyCppHandler::Initialize(&key_, NULL);
+ ValueCppHandler::InitializeMaybeByDefaultEnum(
+ &value_, default_enum_value, NULL);
+ _has_bits_[0] = 0;
+ }
+
+ explicit MapEntryLite(Arena* arena)
+ : default_instance_(NULL), arena_(arena) {
+ KeyCppHandler::Initialize(&key_, arena);
+ ValueCppHandler::InitializeMaybeByDefaultEnum(
+ &value_, default_enum_value, arena);
+ _has_bits_[0] = 0;
+ }
+
+ inline Arena* GetArenaNoVirtual() const {
+ return arena_;
+ }
+
+ void set_default_instance(MapEntryLite* default_instance) {
+ default_instance_ = default_instance;
+ }
+
+ MapEntryLite* default_instance_;
+
+ KeyBase key_;
+ ValueBase value_;
+ Arena* arena_;
+ uint32 _has_bits_[1];
+
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
+ template <typename K, typename V, WireFormatLite::FieldType,
+ WireFormatLite::FieldType, int>
+ friend class internal::MapEntry;
+ template <typename K, typename V, WireFormatLite::FieldType,
+ WireFormatLite::FieldType, int>
+ friend class internal::MapFieldLite;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
+};
+
+} // namespace internal
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc
index b535ec28..6ff1936e 100644
--- a/src/google/protobuf/map_field.cc
+++ b/src/google/protobuf/map_field.cc
@@ -55,14 +55,14 @@ void InitMapEntryDefaultInstances() {
}
void RegisterMapEntryDefaultInstance(MessageLite* default_instance) {
- GoogleOnceInit(&map_entry_default_instances_once_,
+ ::google::protobuf::GoogleOnceInit(&map_entry_default_instances_once_,
&InitMapEntryDefaultInstances);
MutexLock lock(map_entry_default_instances_mutex_);
map_entry_default_instances_->push_back(default_instance);
}
MapFieldBase::~MapFieldBase() {
- if (repeated_field_ != NULL) delete repeated_field_;
+ if (repeated_field_ != NULL && arena_ == NULL) delete repeated_field_;
}
const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const {
@@ -104,32 +104,42 @@ void MapFieldBase::SetRepeatedDirty() { state_ = STATE_MODIFIED_REPEATED; }
void* MapFieldBase::MutableRepeatedPtrField() const { return repeated_field_; }
void MapFieldBase::SyncRepeatedFieldWithMap() const {
- Atomic32 state = google::protobuf::internal::NoBarrier_Load(&state_);
+ // "Acquire" insures the operation after SyncRepeatedFieldWithMap won't get
+ // executed before state_ is checked.
+ Atomic32 state = google::protobuf::internal::Acquire_Load(&state_);
if (state == STATE_MODIFIED_MAP) {
mutex_.Lock();
// Double check state, because another thread may have seen the same state
// and done the synchronization before the current thread.
if (state_ == STATE_MODIFIED_MAP) {
SyncRepeatedFieldWithMapNoLock();
- google::protobuf::internal::NoBarrier_Store(&state_, CLEAN);
+ // "Release" insures state_ can only be changed "after"
+ // SyncRepeatedFieldWithMapNoLock is finished.
+ google::protobuf::internal::Release_Store(&state_, CLEAN);
}
mutex_.Unlock();
}
}
void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const {
- if (repeated_field_ == NULL) repeated_field_ = new RepeatedPtrField<Message>;
+ if (repeated_field_ == NULL) {
+ repeated_field_ = Arena::CreateMessage<RepeatedPtrField<Message> >(arena_);
+ }
}
void MapFieldBase::SyncMapWithRepeatedField() const {
- Atomic32 state = google::protobuf::internal::NoBarrier_Load(&state_);
+ // "Acquire" insures the operation after SyncMapWithRepeatedField won't get
+ // executed before state_ is checked.
+ Atomic32 state = google::protobuf::internal::Acquire_Load(&state_);
if (state == STATE_MODIFIED_REPEATED) {
mutex_.Lock();
// Double check state, because another thread may have seen the same state
// and done the synchronization before the current thread.
if (state_ == STATE_MODIFIED_REPEATED) {
SyncMapWithRepeatedFieldNoLock();
- google::protobuf::internal::NoBarrier_Store(&state_, CLEAN);
+ // "Release" insures state_ can only be changed "after"
+ // SyncRepeatedFieldWithMapNoLock is finished.
+ google::protobuf::internal::Release_Store(&state_, CLEAN);
}
mutex_.Unlock();
}
diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h
index 8516d74e..56d3d0f4 100644
--- a/src/google/protobuf/map_field.h
+++ b/src/google/protobuf/map_field.h
@@ -34,8 +34,10 @@
#include <google/protobuf/stubs/atomicops.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/map.h>
+#include <google/protobuf/arena.h>
#include <google/protobuf/map_entry.h>
+#include <google/protobuf/map_field_lite.h>
+#include <google/protobuf/map_type_handler.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/unknown_field_set.h>
@@ -56,11 +58,21 @@ class MapFieldAccessor;
class LIBPROTOBUF_EXPORT MapFieldBase {
public:
MapFieldBase()
- : base_map_(NULL),
+ : arena_(NULL),
repeated_field_(NULL),
entry_descriptor_(NULL),
assign_descriptor_callback_(NULL),
state_(STATE_MODIFIED_MAP) {}
+ explicit MapFieldBase(Arena* arena)
+ : arena_(arena),
+ repeated_field_(NULL),
+ entry_descriptor_(NULL),
+ assign_descriptor_callback_(NULL),
+ state_(STATE_MODIFIED_MAP) {
+ // Mutex's destructor needs to be called explicitly to release resources
+ // acquired in its constructor.
+ arena->OwnDestructor(&mutex_);
+ }
virtual ~MapFieldBase();
// Returns reference to internal repeated field. Data written using
@@ -109,7 +121,7 @@ class LIBPROTOBUF_EXPORT MapFieldBase {
CLEAN = 2, // data in map and repeated field are same
};
- mutable void* base_map_;
+ Arena* arena_;
mutable RepeatedPtrField<Message>* repeated_field_;
// MapEntry can only be created from MapField. To create MapEntry, MapField
// needs to know its descriptor, because MapEntry is not generated class which
@@ -134,41 +146,55 @@ class LIBPROTOBUF_EXPORT MapFieldBase {
// This class provides accesss to map field using generated api. It is used for
// internal generated message implentation only. Users should never use this
// directly.
-template<typename Key, typename T,
- FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value = 0>
-class MapField : public MapFieldBase {
- // Handlers for key/value's proto field type.
- typedef MapProtoTypeHandler<KeyProto> KeyProtoHandler;
- typedef MapProtoTypeHandler<ValueProto> ValueProtoHandler;
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value = 0>
+class MapField : public MapFieldBase,
+ public MapFieldLite<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value> {
+ // Handlers for key/value wire type. Provide utilities to parse/serialize
+ // key/value.
+ typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler;
+ typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler;
// Define key/value's internal stored type.
- typedef typename KeyProtoHandler::CppType KeyHandlerCpp;
- typedef typename ValueProtoHandler::CppType ValHandlerCpp;
- static const bool kIsKeyMessage = KeyProtoHandler::kIsMessage;
- static const bool kIsValMessage = ValueProtoHandler::kIsMessage;
- typedef typename MapIf<kIsKeyMessage, Key, KeyHandlerCpp>::type KeyCpp;
- typedef typename MapIf<kIsValMessage, T , ValHandlerCpp>::type ValCpp;
+ static const bool kIsKeyMessage = KeyWireHandler::kIsMessage;
+ static const bool kIsValMessage = ValueWireHandler::kIsMessage;
+ typedef typename KeyWireHandler::CppType KeyInternalType;
+ typedef typename ValueWireHandler::CppType ValueInternalType;
+ typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type KeyCpp;
+ typedef typename MapIf<kIsValMessage, T , ValueInternalType>::type ValCpp;
// Handlers for key/value's internal stored type.
typedef MapCppTypeHandler<KeyCpp> KeyHandler;
typedef MapCppTypeHandler<ValCpp> ValHandler;
// Define message type for internal repeated field.
- typedef MapEntry<Key, T, KeyProto, ValueProto, default_enum_value> EntryType;
+ typedef MapEntry<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>
+ EntryType;
+ typedef MapEntryLite<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value> EntryLiteType;
+
+ // Define abbreviation for parent MapFieldLite
+ typedef MapFieldLite<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value> MapFieldLiteType;
// Enum needs to be handled differently from other types because it has
// different exposed type in google::protobuf::Map's api and repeated field's api. For
// details see the comment in the implementation of
// SyncMapWithRepeatedFieldNoLocki.
- static const bool kIsValueEnum = ValueProtoHandler::kIsEnum;
+ static const bool kIsValueEnum = ValueWireHandler::kIsEnum;
typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType;
public:
MapField();
+ explicit MapField(Arena* arena);
// MapField doesn't own the default_entry, which means default_entry must
// outlive the lifetime of MapField.
MapField(const Message* default_entry);
+ // For tests only.
+ MapField(Arena* arena, const Message* default_entry);
~MapField();
// Accessors
@@ -178,29 +204,23 @@ class MapField : public MapFieldBase {
// Convenient methods for generated message implementation.
int size() const;
void Clear();
- void MergeFrom(const MapField& other);
- void Swap(MapField* other);
+ void MergeFrom(const MapFieldLiteType& other);
+ void Swap(MapFieldLiteType* other);
// Allocates metadata only if this MapField is part of a generated message.
void SetEntryDescriptor(const Descriptor** descriptor);
void SetAssignDescriptorCallback(void (*callback)());
- // Set default enum value only for proto2 map field whose value is enum type.
- void SetDefaultEnumValue();
-
- // Used in the implementation of parsing. Caller should take the ownership.
- EntryType* NewEntry() const;
- // Used in the implementation of serializing enum value type. Caller should
- // take the ownership.
- EntryType* NewEnumEntryWrapper(const Key& key, const T t) const;
- // Used in the implementation of serializing other value types. Caller should
- // take the ownership.
- EntryType* NewEntryWrapper(const Key& key, const T& t) const;
-
private:
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
+
// MapField needs MapEntry's default instance to create new MapEntry.
void InitDefaultEntryOnce() const;
+ // Manually set default entry instance. For test only.
+ void SetDefaultEntryOnce(const EntryType* default_entry) const;
+
// Convenient methods to get internal google::protobuf::Map
const Map<Key, T>& GetInternalMap() const;
Map<Key, T>* MutableInternalMap();
@@ -211,14 +231,9 @@ class MapField : public MapFieldBase {
int SpaceUsedExcludingSelfNoLock() const;
mutable const EntryType* default_entry_;
-};
-// True if IsInitialized() is true for value field in all elements of t. T is
-// expected to be message. It's useful to have this helper here to keep the
-// protobuf compiler from ever having to emit loops in IsInitialized() methods.
-// We want the C++ compiler to inline this or not as it sees fit.
-template <typename Key, typename T>
-bool AllAreInitialized(const Map<Key, T>& t);
+ friend class ::google::protobuf::Arena;
+};
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h
index 79302e48..5b4305f9 100644
--- a/src/google/protobuf/map_field_inl.h
+++ b/src/google/protobuf/map_field_inl.h
@@ -43,160 +43,183 @@ namespace google {
namespace protobuf {
namespace internal {
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MapField()
- : default_entry_(NULL) {
- MapFieldBase::base_map_ = new Map<Key, T>;
- SetDefaultEnumValue();
-}
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField()
+ : default_entry_(NULL) {}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField(
+ Arena* arena)
+ : MapFieldBase(arena),
+ MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>(
+ arena),
+ default_entry_(NULL) {}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MapField(
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField(
const Message* default_entry)
- : default_entry_(down_cast<const EntryType*>(default_entry)) {
- MapFieldBase::base_map_ = new Map<Key, T>;
- SetDefaultEnumValue();
-}
+ : default_entry_(down_cast<const EntryType*>(default_entry)) {}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::~MapField() {
- delete reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
-}
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField(
+ Arena* arena, const Message* default_entry)
+ : MapFieldBase(arena),
+ MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>(
+ arena),
+ default_entry_(down_cast<const EntryType*>(default_entry)) {}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-int MapField<Key, T, KeyProto, ValueProto, default_enum_value>::size() const {
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::~MapField() {}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+int
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::size() const {
SyncMapWithRepeatedField();
- return GetInternalMap().size();
+ return MapFieldLiteType::GetInternalMap().size();
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::Clear() {
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::Clear() {
SyncMapWithRepeatedField();
- MutableInternalMap()->clear();
+ MapFieldLiteType::MutableInternalMap()->clear();
SetMapDirty();
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
const Map<Key, T>&
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::GetMap() const {
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::GetMap() const {
SyncMapWithRepeatedField();
- return GetInternalMap();
+ return MapFieldLiteType::GetInternalMap();
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
Map<Key, T>*
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MutableMap() {
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::MutableMap() {
SyncMapWithRepeatedField();
- Map<Key, T>* result = MutableInternalMap();
+ Map<Key, T>* result = MapFieldLiteType::MutableInternalMap();
SetMapDirty();
return result;
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MergeFrom(
- const MapField& other) {
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::MergeFrom(
+ const MapFieldLiteType& other) {
+ const MapField& down_other = down_cast<const MapField&>(other);
SyncMapWithRepeatedField();
- other.SyncMapWithRepeatedField();
-
- Map<Key, T>* map = MutableInternalMap();
- const Map<Key, T>& other_map = other.GetInternalMap();
- for (typename Map<Key, T>::const_iterator it = other_map.begin();
- it != other_map.end(); ++it) {
- (*map)[it->first] = it->second;
- }
+ down_other.SyncMapWithRepeatedField();
+ MapFieldLiteType::MergeFrom(other);
SetMapDirty();
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::Swap(
- MapField* other) {
- std::swap(repeated_field_, other->repeated_field_);
- std::swap(base_map_, other->base_map_);
- std::swap(state_, other->state_);
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::Swap(
+ MapFieldLiteType* other) {
+ MapField* down_other = down_cast<MapField*>(other);
+ std::swap(repeated_field_, down_other->repeated_field_);
+ MapFieldLiteType::Swap(other);
+ std::swap(state_, down_other->state_);
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
void
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::SetEntryDescriptor(
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::SetEntryDescriptor(
const Descriptor** descriptor) {
entry_descriptor_ = descriptor;
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
void
-MapField<Key, T, KeyProto, ValueProto,
+MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::SetAssignDescriptorCallback(void (*callback)()) {
assign_descriptor_callback_ = callback;
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto,
- default_enum_value>::SetDefaultEnumValue() {
- MutableInternalMap()->SetDefaultEnumValue(default_enum_value);
-}
-
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>*
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEntry() const {
- // The MapEntry instance created here is only used in generated code for
- // parsing. It doesn't have default instance, descriptor or reflection,
- // because these are not needed in parsing and will prevent us from using it
- // for parsing MessageLite.
- return new EntryType();
-}
-
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>*
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEntryWrapper(
- const Key& key, const T& t) const {
- return EntryType::Wrap(key, t);
-}
-
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>*
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEnumEntryWrapper(
- const Key& key, const T t) const {
- return EntryType::EnumWrap(key, t);
-}
-
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-const Map<Key, T>& MapField<Key, T, KeyProto, ValueProto,
- default_enum_value>::GetInternalMap() const {
- return *reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+const Map<Key, T>&
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::GetInternalMap() const {
+ return MapFieldLiteType::GetInternalMap();
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-Map<Key, T>* MapField<Key, T, KeyProto, ValueProto,
- default_enum_value>::MutableInternalMap() {
- return reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+Map<Key, T>*
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::MutableInternalMap() {
+ return MapFieldLiteType::MutableInternalMap();
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto,
- default_enum_value>::SyncRepeatedFieldWithMapNoLock() const {
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::SyncRepeatedFieldWithMapNoLock() const {
if (repeated_field_ == NULL) {
- repeated_field_ = new RepeatedPtrField<Message>();
+ if (MapFieldBase::arena_ == NULL) {
+ repeated_field_ = new RepeatedPtrField<Message>();
+ } else {
+ repeated_field_ = Arena::CreateMessage<RepeatedPtrField<Message> >(
+ MapFieldBase::arena_);
+ }
}
- const Map<Key, T>& map =
- *static_cast<const Map<Key, T>*>(MapFieldBase::base_map_);
+ const Map<Key, T>& map = GetInternalMap();
RepeatedPtrField<EntryType>* repeated_field =
reinterpret_cast<RepeatedPtrField<EntryType>*>(repeated_field_);
@@ -206,18 +229,22 @@ void MapField<Key, T, KeyProto, ValueProto,
it != map.end(); ++it) {
InitDefaultEntryOnce();
GOOGLE_CHECK(default_entry_ != NULL);
- EntryType* new_entry = down_cast<EntryType*>(default_entry_->New());
+ EntryType* new_entry =
+ down_cast<EntryType*>(default_entry_->New(MapFieldBase::arena_));
repeated_field->AddAllocated(new_entry);
- new_entry->set_key(it->first);
- new_entry->set_value(it->second);
+ (*new_entry->mutable_key()) = it->first;
+ (*new_entry->mutable_value()) = it->second;
}
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto,
- default_enum_value>::SyncMapWithRepeatedFieldNoLock() const {
- Map<Key, T>* map = reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::SyncMapWithRepeatedFieldNoLock() const {
+ Map<Key, T>* map = const_cast<MapField*>(this)->MutableInternalMap();
RepeatedPtrField<EntryType>* repeated_field =
reinterpret_cast<RepeatedPtrField<EntryType>*>(repeated_field_);
map->clear();
@@ -232,15 +259,18 @@ void MapField<Key, T, KeyProto, ValueProto,
}
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-int MapField<Key, T, KeyProto, ValueProto,
- default_enum_value>::SpaceUsedExcludingSelfNoLock() const {
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+int
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::SpaceUsedExcludingSelfNoLock() const {
int size = 0;
if (repeated_field_ != NULL) {
size += repeated_field_->SpaceUsedExcludingSelf();
}
- Map<Key, T>* map = reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
+ Map<Key, T>* map = const_cast<MapField*>(this)->MutableInternalMap();
size += sizeof(*map);
for (typename Map<Key, T>::iterator it = map->begin();
it != map->end(); ++it) {
@@ -250,10 +280,14 @@ int MapField<Key, T, KeyProto, ValueProto,
return size;
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto,
- default_enum_value>::InitDefaultEntryOnce() const {
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::InitDefaultEntryOnce()
+ const {
if (default_entry_ == NULL) {
InitMetadataOnce();
GOOGLE_CHECK(*entry_descriptor_ != NULL);
@@ -262,15 +296,6 @@ void MapField<Key, T, KeyProto, ValueProto,
}
}
-template <typename Key, typename T>
-bool AllAreInitialized(const Map<Key, T>& t) {
- for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
- ++it) {
- if (!it->second.IsInitialized()) return false;
- }
- return true;
-}
-
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h
new file mode 100644
index 00000000..860dae55
--- /dev/null
+++ b/src/google/protobuf/map_field_lite.h
@@ -0,0 +1,278 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
+
+#include <google/protobuf/map.h>
+#include <google/protobuf/map_entry_lite.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// This class provides accesss to map field using generated api. It is used for
+// internal generated message implentation only. Users should never use this
+// directly.
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value = 0>
+class MapFieldLite {
+ // Define message type for internal repeated field.
+ typedef MapEntryLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value> EntryType;
+
+ public:
+ MapFieldLite();
+ explicit MapFieldLite(Arena* arena);
+ virtual ~MapFieldLite();
+
+ // Accessors
+ virtual const Map<Key, T>& GetMap() const;
+ virtual Map<Key, T>* MutableMap();
+
+ // Convenient methods for generated message implementation.
+ virtual int size() const;
+ virtual void Clear();
+ virtual void MergeFrom(const MapFieldLite& other);
+ virtual void Swap(MapFieldLite* other);
+
+ // Set default enum value only for proto2 map field whose value is enum type.
+ void SetDefaultEnumValue();
+
+ // Used in the implementation of parsing. Caller should take the ownership.
+ EntryType* NewEntry() const;
+ // Used in the implementation of serializing enum value type. Caller should
+ // take the ownership.
+ EntryType* NewEnumEntryWrapper(const Key& key, const T t) const;
+ // Used in the implementation of serializing other value types. Caller should
+ // take the ownership.
+ EntryType* NewEntryWrapper(const Key& key, const T& t) const;
+
+ protected:
+ // Convenient methods to get internal google::protobuf::Map
+ virtual const Map<Key, T>& GetInternalMap() const;
+ virtual Map<Key, T>* MutableInternalMap();
+
+ private:
+ typedef void DestructorSkippable_;
+
+ Arena* arena_;
+ Map<Key, T>* map_;
+
+ friend class ::google::protobuf::Arena;
+};
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::MapFieldLite()
+ : arena_(NULL) {
+ map_ = new Map<Key, T>;
+ SetDefaultEnumValue();
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::MapFieldLite(Arena* arena)
+ : arena_(arena) {
+ map_ = Arena::CreateMessage<Map<Key, T> >(arena);
+ SetDefaultEnumValue();
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::~MapFieldLite() {
+ delete map_;
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+const Map<Key, T>&
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::GetMap() const {
+ return *map_;
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+Map<Key, T>*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::MutableMap() {
+ return map_;
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+int
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::size() const {
+ return map_->size();
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+void
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::Clear() {
+ map_->clear();
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+void
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::MergeFrom(
+ const MapFieldLite& other) {
+ for (typename Map<Key, T>::const_iterator it = other.map_->begin();
+ it != other.map_->end(); ++it) {
+ (*map_)[it->first] = it->second;
+ }
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+void
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::Swap(
+ MapFieldLite* other) {
+ std::swap(map_, other->map_);
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+void
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::SetDefaultEnumValue() {
+ MutableInternalMap()->SetDefaultEnumValue(default_enum_value);
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+const Map<Key, T>&
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::GetInternalMap() const {
+ return *map_;
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+Map<Key, T>*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::MutableInternalMap() {
+ return map_;
+}
+
+#define EntryType \
+ MapEntryLite<Key, T, key_wire_type, value_wire_type, default_enum_value>
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+EntryType*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::NewEntry() const {
+ if (arena_ == NULL) {
+ return new EntryType();
+ } else {
+ return Arena::CreateMessage<EntryType>(arena_);
+ }
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+EntryType*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::NewEnumEntryWrapper(const Key& key,
+ const T t) const {
+ return EntryType::EnumWrap(key, t, arena_);
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+EntryType*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::NewEntryWrapper(const Key& key,
+ const T& t) const {
+ return EntryType::Wrap(key, t, arena_);
+}
+
+#undef EntryType
+
+// True if IsInitialized() is true for value field in all elements of t. T is
+// expected to be message. It's useful to have this helper here to keep the
+// protobuf compiler from ever having to emit loops in IsInitialized() methods.
+// We want the C++ compiler to inline this or not as it sees fit.
+template <typename Key, typename T>
+bool AllAreInitialized(const Map<Key, T>& t) {
+ for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
+ ++it) {
+ if (!it->second.IsInitialized()) return false;
+ }
+ return true;
+}
+
+} // namespace internal
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc
index 045f8f2c..e3a64079 100644
--- a/src/google/protobuf/map_field_test.cc
+++ b/src/google/protobuf/map_field_test.cc
@@ -35,13 +35,16 @@
#endif
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arena.h>
#include <google/protobuf/map.h>
+#include <google/protobuf/arena_test_util.h>
#include <google/protobuf/map_unittest.pb.h>
#include <google/protobuf/map_test_util.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/map_field_inl.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/wire_format_lite_inl.h>
#include <gtest/gtest.h>
namespace google {
@@ -53,6 +56,10 @@ using unittest::TestAllTypes;
class MapFieldBaseStub : public MapFieldBase {
public:
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
+ MapFieldBaseStub() {}
+ explicit MapFieldBaseStub(Arena* arena) : MapFieldBase(arena) {}
void SyncRepeatedFieldWithMap() const {
MapFieldBase::SyncRepeatedFieldWithMap();
}
@@ -63,16 +70,6 @@ class MapFieldBaseStub : public MapFieldBase {
RepeatedPtrField<Message>* InternalRepeatedField() {
return repeated_field_;
}
- // Get underlined map without synchronizing repeated field.
- template <typename MapType>
- const MapType& GetMap() {
- return *reinterpret_cast<MapType*>(base_map_);
- }
- // Get underlined map without synchronizing repeated field.
- template <typename MapType>
- MapType* MutableMap() {
- return reinterpret_cast<MapType*>(base_map_);
- }
bool IsMapClean() { return state_ != 0; }
bool IsRepeatedClean() { return state_ != 1; }
void SetMapDirty() { state_ = 0; }
@@ -81,8 +78,8 @@ class MapFieldBaseStub : public MapFieldBase {
class MapFieldBasePrimitiveTest : public ::testing::Test {
protected:
- typedef MapField<int32, int32, FieldDescriptor::TYPE_INT32,
- FieldDescriptor::TYPE_INT32> MapFieldType;
+ typedef MapField<int32, int32, WireFormatLite::TYPE_INT32,
+ WireFormatLite::TYPE_INT32, false> MapFieldType;
MapFieldBasePrimitiveTest() {
// Get descriptors
@@ -144,6 +141,42 @@ TEST_F(MapFieldBasePrimitiveTest, MutableRepeatedField) {
}
}
+TEST_F(MapFieldBasePrimitiveTest, Arena) {
+ // Allocate a large initial block to avoid mallocs during hooked test.
+ std::vector<char> arena_block(128 * 1024);
+ ArenaOptions options;
+ options.initial_block = &arena_block[0];
+ options.initial_block_size = arena_block.size();
+ Arena arena(options);
+
+ {
+ // TODO(liujisi): Re-write the test to ensure the memory for the map and
+ // repeated fields are allocated from arenas.
+ // NoHeapChecker no_heap;
+
+ MapFieldType* map_field =
+ Arena::CreateMessage<MapFieldType>(&arena, default_entry_);
+
+ // Set content in map
+ (*map_field->MutableMap())[100] = 101;
+
+ // Trigger conversion to repeated field.
+ map_field->GetRepeatedField();
+ }
+
+ {
+ // TODO(liujisi): Re-write the test to ensure the memory for the map and
+ // repeated fields are allocated from arenas.
+ // NoHeapChecker no_heap;
+
+ MapFieldBaseStub* map_field =
+ Arena::CreateMessage<MapFieldBaseStub>(&arena);
+
+ // Trigger conversion to repeated field.
+ EXPECT_TRUE(map_field->MutableRepeatedField() != NULL);
+ }
+}
+
namespace {
enum State { CLEAN, MAP_DIRTY, REPEATED_DIRTY };
} // anonymous namespace
@@ -152,8 +185,10 @@ class MapFieldStateTest
: public testing::TestWithParam<State> {
public:
protected:
- typedef MapField<int32, int32, FieldDescriptor::TYPE_INT32,
- FieldDescriptor::TYPE_INT32> MapFieldType;
+ typedef MapField<int32, int32, WireFormatLite::TYPE_INT32,
+ WireFormatLite::TYPE_INT32, false> MapFieldType;
+ typedef MapFieldLite<int32, int32, WireFormatLite::TYPE_INT32,
+ WireFormatLite::TYPE_INT32, false> MapFieldLiteType;
MapFieldStateTest() : state_(GetParam()) {
// Build map field
const Descriptor* map_descriptor =
@@ -199,9 +234,8 @@ class MapFieldStateTest
MakeMapDirty(map_field);
MapFieldBase* map_field_base = map_field;
map_field_base->MutableRepeatedField();
- MapFieldBaseStub* stub =
- reinterpret_cast<MapFieldBaseStub*>(map_field_base);
- Map<int32, int32>* map = stub->MutableMap<Map<int32, int32> >();
+ Map<int32, int32>* map = implicit_cast<MapFieldLiteType*>(map_field)
+ ->MapFieldLiteType::MutableMap();
map->clear();
Expect(map_field, REPEATED_DIRTY, 0, 1, false);
@@ -213,7 +247,8 @@ class MapFieldStateTest
MapFieldBaseStub* stub =
reinterpret_cast<MapFieldBaseStub*>(map_field_base);
- Map<int32, int32>* map = stub->MutableMap<Map<int32, int32> >();
+ Map<int32, int32>* map = implicit_cast<MapFieldLiteType*>(map_field)
+ ->MapFieldLiteType::MutableMap();
RepeatedPtrField<Message>* repeated_field = stub->InternalRepeatedField();
switch (state) {
@@ -430,6 +465,7 @@ TEST_P(MapFieldStateTest, MutableMapField) {
}
}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/map_lite_test_util.cc b/src/google/protobuf/map_lite_test_util.cc
new file mode 100644
index 00000000..b65b4d63
--- /dev/null
+++ b/src/google/protobuf/map_lite_test_util.cc
@@ -0,0 +1,93 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/map_lite_test_util.h>
+#include <google/protobuf/map_lite_unittest.pb.h>
+#include <google/protobuf/map_test_util_impl.h>
+
+namespace google {
+namespace protobuf {
+
+void MapLiteTestUtil::SetMapFields(unittest::TestMapLite* message) {
+ MapTestUtilImpl::SetMapFields<unittest::MapEnumLite,
+ unittest::MAP_ENUM_BAR_LITE,
+ unittest::MAP_ENUM_BAZ_LITE>(message);
+}
+
+void MapLiteTestUtil::SetArenaMapFields(unittest::TestArenaMapLite* message) {
+ MapTestUtilImpl::SetArenaMapFields<unittest::MapEnumLite,
+ unittest::MAP_ENUM_BAR_LITE,
+ unittest::MAP_ENUM_BAZ_LITE>(message);
+}
+
+void MapLiteTestUtil::SetMapFieldsInitialized(unittest::TestMapLite* message) {
+ MapTestUtilImpl::SetMapFieldsInitialized(message);
+}
+
+void MapLiteTestUtil::ModifyMapFields(unittest::TestMapLite* message) {
+ MapTestUtilImpl::ModifyMapFields<unittest::MapEnumLite,
+ unittest::MAP_ENUM_FOO_LITE>(message);
+}
+
+void MapLiteTestUtil::ExpectClear(const unittest::TestMapLite& message) {
+ MapTestUtilImpl::ExpectClear(message);
+}
+
+void MapLiteTestUtil::ExpectMapFieldsSet(const unittest::TestMapLite& message) {
+ MapTestUtilImpl::ExpectMapFieldsSet<unittest::MapEnumLite,
+ unittest::MAP_ENUM_BAR_LITE,
+ unittest::MAP_ENUM_BAZ_LITE>(message);
+}
+
+void MapLiteTestUtil::ExpectArenaMapFieldsSet(
+ const unittest::TestArenaMapLite& message) {
+ MapTestUtilImpl::ExpectArenaMapFieldsSet<unittest::MapEnumLite,
+ unittest::MAP_ENUM_BAR_LITE,
+ unittest::MAP_ENUM_BAZ_LITE>(
+ message);
+}
+
+void MapLiteTestUtil::ExpectMapFieldsSetInitialized(
+ const unittest::TestMapLite& message) {
+ MapTestUtilImpl::ExpectMapFieldsSetInitialized<unittest::MapEnumLite,
+ unittest::MAP_ENUM_FOO_LITE>(
+ message);
+}
+
+void MapLiteTestUtil::ExpectMapFieldsModified(
+ const unittest::TestMapLite& message) {
+ MapTestUtilImpl::ExpectMapFieldsModified<unittest::MapEnumLite,
+ unittest::MAP_ENUM_BAR_LITE,
+ unittest::MAP_ENUM_FOO_LITE>(
+ message);
+}
+
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/map_lite_test_util.h b/src/google/protobuf/map_lite_test_util.h
new file mode 100644
index 00000000..77b5336f
--- /dev/null
+++ b/src/google/protobuf/map_lite_test_util.h
@@ -0,0 +1,80 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__
+#define GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__
+
+#include <google/protobuf/map_lite_unittest.pb.h>
+
+namespace google {
+namespace protobuf {
+
+class MapLiteTestUtil {
+ public:
+ // Set every field in the TestMapLite message to a unique value.
+ static void SetMapFields(protobuf_unittest::TestMapLite* message);
+
+ // Set every field in the TestArenaMapLite message to a unique value.
+ static void SetArenaMapFields(protobuf_unittest::TestArenaMapLite* message);
+
+ // Set every field in the message to a default value.
+ static void SetMapFieldsInitialized(protobuf_unittest::TestMapLite* message);
+
+ // Modify all the map fields of the messsage (which should already have been
+ // initialized with SetMapFields()).
+ static void ModifyMapFields(protobuf_unittest::TestMapLite* message);
+
+ // Check that all fields have the values that they should have after
+ // SetMapFields() is called.
+ static void ExpectMapFieldsSet(const protobuf_unittest::TestMapLite& message);
+
+ // Check that all fields have the values that they should have after
+ // SetMapFields() is called for TestArenaMapLite.
+ static void ExpectArenaMapFieldsSet(
+ const protobuf_unittest::TestArenaMapLite& message);
+
+ // Check that all fields have the values that they should have after
+ // SetMapFieldsInitialized() is called.
+ static void ExpectMapFieldsSetInitialized(
+ const protobuf_unittest::TestMapLite& message);
+
+ // Expect that the message is modified as would be expected from
+ // ModifyMapFields().
+ static void ExpectMapFieldsModified(
+ const protobuf_unittest::TestMapLite& message);
+
+ // Check that all fields are empty.
+ static void ExpectClear(const protobuf_unittest::TestMapLite& message);
+};
+
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__
diff --git a/src/google/protobuf/map_lite_unittest.proto b/src/google/protobuf/map_lite_unittest.proto
index cc71555d..c69e8d94 100644
--- a/src/google/protobuf/map_lite_unittest.proto
+++ b/src/google/protobuf/map_lite_unittest.proto
@@ -30,10 +30,104 @@
syntax = "proto2";
+option cc_enable_arenas = true;
option optimize_for = LITE_RUNTIME;
+import "google/protobuf/unittest_lite.proto";
+
package protobuf_unittest;
-message MapLite {
- map<int32, int32> map_field = 1;
+message TestMapLite {
+ map<int32 , int32 > map_int32_int32 = 1;
+ map<int64 , int64 > map_int64_int64 = 2;
+ map<uint32 , uint32 > map_uint32_uint32 = 3;
+ map<uint64 , uint64 > map_uint64_uint64 = 4;
+ map<sint32 , sint32 > map_sint32_sint32 = 5;
+ map<sint64 , sint64 > map_sint64_sint64 = 6;
+ map<fixed32 , fixed32 > map_fixed32_fixed32 = 7;
+ map<fixed64 , fixed64 > map_fixed64_fixed64 = 8;
+ map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+ map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+ map<int32 , float > map_int32_float = 11;
+ map<int32 , double > map_int32_double = 12;
+ map<bool , bool > map_bool_bool = 13;
+ map<string , string > map_string_string = 14;
+ map<int32 , bytes > map_int32_bytes = 15;
+ map<int32 , MapEnumLite> map_int32_enum = 16;
+ map<int32 , ForeignMessageLite> map_int32_foreign_message = 17;
+ map<int32, int32> teboring = 18;
+}
+
+message TestArenaMapLite {
+ map<int32 , int32 > map_int32_int32 = 1;
+ map<int64 , int64 > map_int64_int64 = 2;
+ map<uint32 , uint32 > map_uint32_uint32 = 3;
+ map<uint64 , uint64 > map_uint64_uint64 = 4;
+ map<sint32 , sint32 > map_sint32_sint32 = 5;
+ map<sint64 , sint64 > map_sint64_sint64 = 6;
+ map<fixed32 , fixed32 > map_fixed32_fixed32 = 7;
+ map<fixed64 , fixed64 > map_fixed64_fixed64 = 8;
+ map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+ map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+ map<int32 , float > map_int32_float = 11;
+ map<int32 , double > map_int32_double = 12;
+ map<bool , bool > map_bool_bool = 13;
+ map<int32 , MapEnumLite> map_int32_enum = 14;
+ map<int32 , ForeignMessageArenaLite> map_int32_foreign_message = 15;
+}
+
+// Test embeded message with required fields
+message TestRequiredMessageMapLite {
+ map<int32, TestRequiredLite> map_field = 1;
+}
+
+message TestEnumStartWithNonZeroMapLite {
+ map<int32, Proto2MapEnumStartWithNonZeroLite> map_field = 101;
+}
+
+message TestEnumMapLite {
+ map<int32, Proto2MapEnumLite> known_map_field = 101;
+ map<int32, Proto2MapEnumLite> unknown_map_field = 102;
+}
+
+message TestEnumMapPlusExtraLite {
+ map<int32, Proto2MapEnumPlusExtraLite> known_map_field = 101;
+ map<int32, Proto2MapEnumPlusExtraLite> unknown_map_field = 102;
+}
+
+message TestMessageMapLite {
+ map<int32, TestAllTypesLite> map_int32_message = 1;
+}
+
+enum Proto2MapEnumLite {
+ PROTO2_MAP_ENUM_FOO_LITE = 0;
+ PROTO2_MAP_ENUM_BAR_LITE = 1;
+ PROTO2_MAP_ENUM_BAZ_LITE = 2;
+}
+
+enum Proto2MapEnumPlusExtraLite {
+ E_PROTO2_MAP_ENUM_FOO_LITE = 0;
+ E_PROTO2_MAP_ENUM_BAR_LITE = 1;
+ E_PROTO2_MAP_ENUM_BAZ_LITE = 2;
+ E_PROTO2_MAP_ENUM_EXTRA_LITE = 3;
+}
+
+enum Proto2MapEnumStartWithNonZeroLite {
+ PROTO2_NON_ZERO_MAP_ENUM_FOO_LITE = 1;
+}
+
+enum MapEnumLite {
+ MAP_ENUM_FOO_LITE = 0;
+ MAP_ENUM_BAR_LITE = 1;
+ MAP_ENUM_BAZ_LITE = 2;
+}
+
+message TestRequiredLite {
+ required int32 a = 1;
+ required int32 b = 2;
+ required int32 c = 3;
+}
+
+message ForeignMessageArenaLite {
+ optional int32 c = 1;
}
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index 9db67523..d62ec85f 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -39,7 +39,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/testing/file.h>
-#include <google/protobuf/map_lite_unittest.pb.h>
+#include <google/protobuf/arena_test_util.h>
#include <google/protobuf/map_proto2_unittest.pb.h>
#include <google/protobuf/map_unittest.pb.h>
#include <google/protobuf/map_test_util.h>
@@ -191,6 +191,7 @@ TEST_F(MapImplTest, MutableAt) {
}
#ifdef PROTOBUF_HAS_DEATH_TEST
+
TEST_F(MapImplTest, MutableAtNonExistDeathTest) {
EXPECT_DEATH(map_.at(0), "");
}
@@ -198,6 +199,7 @@ TEST_F(MapImplTest, MutableAtNonExistDeathTest) {
TEST_F(MapImplTest, ImmutableAtNonExistDeathTest) {
EXPECT_DEATH(const_map_.at(0), "");
}
+
#endif // PROTOBUF_HAS_DEATH_TEST
TEST_F(MapImplTest, CountNonExist) {
@@ -553,6 +555,14 @@ TEST_F(MapImplTest, ConvertToStdMap) {
EXPECT_EQ(101, std_map[100]);
}
+TEST_F(MapImplTest, ConvertToStdVectorOfPairs) {
+ map_[100] = 101;
+ std::vector<std::pair<int32, int32> > std_vec(map_.begin(), map_.end());
+ EXPECT_EQ(1, std_vec.size());
+ EXPECT_EQ(100, std_vec[0].first);
+ EXPECT_EQ(101, std_vec[0].second);
+}
+
// Map Field Reflection Test ========================================
static int Func(int i, int j) {
@@ -1717,6 +1727,20 @@ TEST(GeneratedMapFieldTest, MissedValueWireFormat) {
EXPECT_EQ(0, message.map_int32_int32().at(1));
}
+TEST(GeneratedMapFieldTest, MissedValueTextFormat) {
+ unittest::TestMap message;
+
+ // No value field in text format
+ string text =
+ "map_int32_foreign_message {\n"
+ " key: 1234567890\n"
+ "}";
+
+ EXPECT_TRUE(google::protobuf::TextFormat::ParseFromString(text, &message));
+ EXPECT_EQ(1, message.map_int32_foreign_message().size());
+ EXPECT_EQ(11, message.ByteSize());
+}
+
TEST(GeneratedMapFieldTest, UnknownFieldWireFormat) {
unittest::TestMap message;
@@ -1737,18 +1761,6 @@ TEST(GeneratedMapFieldTest, CorruptedWireFormat) {
EXPECT_FALSE(message.ParseFromString(data));
}
-TEST(GeneratedMapFieldTest, MessageLiteMap) {
- unittest::MapLite from, to;
- (*from.mutable_map_field())[1] = 1;
-
- string data;
- from.SerializeToString(&data);
- to.ParseFromString(data);
-
- EXPECT_EQ(1, to.map_field().size());
- EXPECT_EQ(1, to.map_field().at(1));
-}
-
TEST(GeneratedMapFieldTest, IsInitialized) {
unittest::TestRequiredMessageMap map_message;
@@ -2246,6 +2258,73 @@ TEST(TextFormatMapTest, SerializeAndParse) {
MapTestUtil::ExpectMapFieldsSet(dest);
}
+TEST(TextFormatMapTest, Sorted) {
+ unittest::TestMap message;
+ MapTestUtil::MapReflectionTester tester(message.GetDescriptor());
+ tester.SetMapFieldsViaReflection(&message);
+
+ string expected_text;
+ GOOGLE_CHECK_OK(File::GetContents(
+ TestSourceDir() +
+ "/google/protobuf/"
+ "testdata/map_test_data.txt",
+ &expected_text, true));
+
+ EXPECT_EQ(message.DebugString(), expected_text);
+
+ // Test again on the reverse order.
+ unittest::TestMap message2;
+ tester.SetMapFieldsViaReflection(&message2);
+ tester.SwapMapsViaReflection(&message2);
+ EXPECT_EQ(message2.DebugString(), expected_text);
+}
+
+
+// arena support =================================================
+TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) {
+ // Allocate a large initial block to avoid mallocs during hooked test.
+ std::vector<char> arena_block(128 * 1024);
+ ArenaOptions options;
+ options.initial_block = &arena_block[0];
+ options.initial_block_size = arena_block.size();
+ Arena arena(options);
+ string data;
+ data.reserve(128 * 1024);
+
+ {
+ NoHeapChecker no_heap;
+
+ unittest::TestArenaMap* from =
+ Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+ MapTestUtil::SetArenaMapFields(from);
+ from->SerializeToString(&data);
+
+ unittest::TestArenaMap* to =
+ Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+ to->ParseFromString(data);
+ MapTestUtil::ExpectArenaMapFieldsSet(*to);
+ }
+}
+
+// Use text format parsing and serializing to test reflection api.
+TEST(ArenaTest, RelfectionInTextFormat) {
+ Arena arena;
+ string data;
+
+ TextFormat::Printer printer;
+ TextFormat::Parser parser;
+
+ unittest::TestArenaMap* from =
+ Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+ unittest::TestArenaMap* to =
+ Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+
+ MapTestUtil::SetArenaMapFields(from);
+ printer.PrintToString(*from, &data);
+
+ EXPECT_TRUE(parser.ParseFromString(data, to));
+ MapTestUtil::ExpectArenaMapFieldsSet(*to);
+}
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/map_test_util.cc b/src/google/protobuf/map_test_util.cc
index eb7ea511..1713e373 100644
--- a/src/google/protobuf/map_test_util.cc
+++ b/src/google/protobuf/map_test_util.cc
@@ -29,275 +29,60 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <google/protobuf/map_test_util.h>
+#include <google/protobuf/map_test_util_impl.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
-
namespace google {
namespace protobuf {
void MapTestUtil::SetMapFields(unittest::TestMap* message) {
- // Add first element.
- (*message->mutable_map_int32_int32())[0] = 0;
- (*message->mutable_map_int64_int64())[0] = 0;
- (*message->mutable_map_uint32_uint32())[0] = 0;
- (*message->mutable_map_uint64_uint64())[0] = 0;
- (*message->mutable_map_sint32_sint32())[0] = 0;
- (*message->mutable_map_sint64_sint64())[0] = 0;
- (*message->mutable_map_fixed32_fixed32())[0] = 0;
- (*message->mutable_map_fixed64_fixed64())[0] = 0;
- (*message->mutable_map_sfixed32_sfixed32())[0] = 0;
- (*message->mutable_map_sfixed64_sfixed64())[0] = 0;
- (*message->mutable_map_int32_float())[0] = 0.0;
- (*message->mutable_map_int32_double())[0] = 0.0;
- (*message->mutable_map_bool_bool())[0] = false;
- (*message->mutable_map_string_string())["0"] = "0";
- (*message->mutable_map_int32_bytes())[0] = "0";
- (*message->mutable_map_int32_enum())[0] =
- unittest::MAP_ENUM_BAR;
- (*message->mutable_map_int32_foreign_message())[0].set_c(0);
+ MapTestUtilImpl::SetMapFields<unittest::MapEnum, unittest::MAP_ENUM_BAR,
+ unittest::MAP_ENUM_BAZ>(message);
+}
- // Add second element
- (*message->mutable_map_int32_int32())[1] = 1;
- (*message->mutable_map_int64_int64())[1] = 1;
- (*message->mutable_map_uint32_uint32())[1] = 1;
- (*message->mutable_map_uint64_uint64())[1] = 1;
- (*message->mutable_map_sint32_sint32())[1] = 1;
- (*message->mutable_map_sint64_sint64())[1] = 1;
- (*message->mutable_map_fixed32_fixed32())[1] = 1;
- (*message->mutable_map_fixed64_fixed64())[1] = 1;
- (*message->mutable_map_sfixed32_sfixed32())[1] = 1;
- (*message->mutable_map_sfixed64_sfixed64())[1] = 1;
- (*message->mutable_map_int32_float())[1] = 1.0;
- (*message->mutable_map_int32_double())[1] = 1.0;
- (*message->mutable_map_bool_bool())[1] = true;
- (*message->mutable_map_string_string())["1"] = "1";
- (*message->mutable_map_int32_bytes())[1] = "1";
- (*message->mutable_map_int32_enum())[1] =
- unittest::MAP_ENUM_BAZ;
- (*message->mutable_map_int32_foreign_message())[1].set_c(1);
+void MapTestUtil::SetArenaMapFields(unittest::TestArenaMap* message) {
+ MapTestUtilImpl::SetArenaMapFields<unittest::MapEnum, unittest::MAP_ENUM_BAR,
+ unittest::MAP_ENUM_BAZ>(message);
}
void MapTestUtil::SetMapFieldsInitialized(unittest::TestMap* message) {
- // Add first element using bracket operator, which should assign default
- // value automatically.
- (*message->mutable_map_int32_int32())[0];
- (*message->mutable_map_int64_int64())[0];
- (*message->mutable_map_uint32_uint32())[0];
- (*message->mutable_map_uint64_uint64())[0];
- (*message->mutable_map_sint32_sint32())[0];
- (*message->mutable_map_sint64_sint64())[0];
- (*message->mutable_map_fixed32_fixed32())[0];
- (*message->mutable_map_fixed64_fixed64())[0];
- (*message->mutable_map_sfixed32_sfixed32())[0];
- (*message->mutable_map_sfixed64_sfixed64())[0];
- (*message->mutable_map_int32_float())[0];
- (*message->mutable_map_int32_double())[0];
- (*message->mutable_map_bool_bool())[0];
- (*message->mutable_map_string_string())["0"];
- (*message->mutable_map_int32_bytes())[0];
- (*message->mutable_map_int32_enum())[0];
- (*message->mutable_map_int32_foreign_message())[0];
+ MapTestUtilImpl::SetMapFieldsInitialized(message);
}
void MapTestUtil::ModifyMapFields(unittest::TestMap* message) {
- (*message->mutable_map_int32_int32())[1] = 2;
- (*message->mutable_map_int64_int64())[1] = 2;
- (*message->mutable_map_uint32_uint32())[1] = 2;
- (*message->mutable_map_uint64_uint64())[1] = 2;
- (*message->mutable_map_sint32_sint32())[1] = 2;
- (*message->mutable_map_sint64_sint64())[1] = 2;
- (*message->mutable_map_fixed32_fixed32())[1] = 2;
- (*message->mutable_map_fixed64_fixed64())[1] = 2;
- (*message->mutable_map_sfixed32_sfixed32())[1] = 2;
- (*message->mutable_map_sfixed64_sfixed64())[1] = 2;
- (*message->mutable_map_int32_float())[1] = 2.0;
- (*message->mutable_map_int32_double())[1] = 2.0;
- (*message->mutable_map_bool_bool())[1] = false;
- (*message->mutable_map_string_string())["1"] = "2";
- (*message->mutable_map_int32_bytes())[1] = "2";
- (*message->mutable_map_int32_enum())[1] =
- unittest::MAP_ENUM_FOO;
- (*message->mutable_map_int32_foreign_message())[1].set_c(2);
+ MapTestUtilImpl::ModifyMapFields<unittest::MapEnum, unittest::MAP_ENUM_FOO>(
+ message);
}
void MapTestUtil::ExpectClear(const unittest::TestMap& message) {
- EXPECT_EQ(0, message.map_int32_int32().size());
- EXPECT_EQ(0, message.map_int64_int64().size());
- EXPECT_EQ(0, message.map_uint32_uint32().size());
- EXPECT_EQ(0, message.map_uint64_uint64().size());
- EXPECT_EQ(0, message.map_sint32_sint32().size());
- EXPECT_EQ(0, message.map_sint64_sint64().size());
- EXPECT_EQ(0, message.map_fixed32_fixed32().size());
- EXPECT_EQ(0, message.map_fixed64_fixed64().size());
- EXPECT_EQ(0, message.map_sfixed32_sfixed32().size());
- EXPECT_EQ(0, message.map_sfixed64_sfixed64().size());
- EXPECT_EQ(0, message.map_int32_float().size());
- EXPECT_EQ(0, message.map_int32_double().size());
- EXPECT_EQ(0, message.map_bool_bool().size());
- EXPECT_EQ(0, message.map_string_string().size());
- EXPECT_EQ(0, message.map_int32_bytes().size());
- EXPECT_EQ(0, message.map_int32_enum().size());
- EXPECT_EQ(0, message.map_int32_foreign_message().size());
+ MapTestUtilImpl::ExpectClear(message);
}
void MapTestUtil::ExpectMapFieldsSet(const unittest::TestMap& message) {
- EXPECT_EQ(2, message.map_int32_int32().size());
- EXPECT_EQ(2, message.map_int64_int64().size());
- EXPECT_EQ(2, message.map_uint32_uint32().size());
- EXPECT_EQ(2, message.map_uint64_uint64().size());
- EXPECT_EQ(2, message.map_sint32_sint32().size());
- EXPECT_EQ(2, message.map_sint64_sint64().size());
- EXPECT_EQ(2, message.map_fixed32_fixed32().size());
- EXPECT_EQ(2, message.map_fixed64_fixed64().size());
- EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
- EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
- EXPECT_EQ(2, message.map_int32_float().size());
- EXPECT_EQ(2, message.map_int32_double().size());
- EXPECT_EQ(2, message.map_bool_bool().size());
- EXPECT_EQ(2, message.map_string_string().size());
- EXPECT_EQ(2, message.map_int32_bytes().size());
- EXPECT_EQ(2, message.map_int32_enum().size());
- EXPECT_EQ(2, message.map_int32_foreign_message().size());
-
- EXPECT_EQ(0, message.map_int32_int32().at(0));
- EXPECT_EQ(0, message.map_int64_int64().at(0));
- EXPECT_EQ(0, message.map_uint32_uint32().at(0));
- EXPECT_EQ(0, message.map_uint64_uint64().at(0));
- EXPECT_EQ(0, message.map_sint32_sint32().at(0));
- EXPECT_EQ(0, message.map_sint64_sint64().at(0));
- EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
- EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
- EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
- EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
- EXPECT_EQ(0, message.map_int32_float().at(0));
- EXPECT_EQ(0, message.map_int32_double().at(0));
- EXPECT_EQ(false, message.map_bool_bool().at(0));
- EXPECT_EQ("0", message.map_string_string().at("0"));
- EXPECT_EQ("0", message.map_int32_bytes().at(0));
- EXPECT_EQ(unittest::MAP_ENUM_BAR, message.map_int32_enum().at(0));
- EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
-
- EXPECT_EQ(1, message.map_int32_int32().at(1));
- EXPECT_EQ(1, message.map_int64_int64().at(1));
- EXPECT_EQ(1, message.map_uint32_uint32().at(1));
- EXPECT_EQ(1, message.map_uint64_uint64().at(1));
- EXPECT_EQ(1, message.map_sint32_sint32().at(1));
- EXPECT_EQ(1, message.map_sint64_sint64().at(1));
- EXPECT_EQ(1, message.map_fixed32_fixed32().at(1));
- EXPECT_EQ(1, message.map_fixed64_fixed64().at(1));
- EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1));
- EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1));
- EXPECT_EQ(1, message.map_int32_float().at(1));
- EXPECT_EQ(1, message.map_int32_double().at(1));
- EXPECT_EQ(true, message.map_bool_bool().at(1));
- EXPECT_EQ("1", message.map_string_string().at("1"));
- EXPECT_EQ("1", message.map_int32_bytes().at(1));
- EXPECT_EQ(unittest::MAP_ENUM_BAZ, message.map_int32_enum().at(1));
- EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c());
+ MapTestUtilImpl::ExpectMapFieldsSet<unittest::MapEnum, unittest::MAP_ENUM_BAR,
+ unittest::MAP_ENUM_BAZ>(message);
+}
+
+void MapTestUtil::ExpectArenaMapFieldsSet(
+ const unittest::TestArenaMap& message) {
+ MapTestUtilImpl::ExpectArenaMapFieldsSet<
+ unittest::MapEnum, unittest::MAP_ENUM_BAR, unittest::MAP_ENUM_BAZ>(
+ message);
}
void MapTestUtil::ExpectMapFieldsSetInitialized(
const unittest::TestMap& message) {
- EXPECT_EQ(1, message.map_int32_int32().size());
- EXPECT_EQ(1, message.map_int64_int64().size());
- EXPECT_EQ(1, message.map_uint32_uint32().size());
- EXPECT_EQ(1, message.map_uint64_uint64().size());
- EXPECT_EQ(1, message.map_sint32_sint32().size());
- EXPECT_EQ(1, message.map_sint64_sint64().size());
- EXPECT_EQ(1, message.map_fixed32_fixed32().size());
- EXPECT_EQ(1, message.map_fixed64_fixed64().size());
- EXPECT_EQ(1, message.map_sfixed32_sfixed32().size());
- EXPECT_EQ(1, message.map_sfixed64_sfixed64().size());
- EXPECT_EQ(1, message.map_int32_float().size());
- EXPECT_EQ(1, message.map_int32_double().size());
- EXPECT_EQ(1, message.map_bool_bool().size());
- EXPECT_EQ(1, message.map_string_string().size());
- EXPECT_EQ(1, message.map_int32_bytes().size());
- EXPECT_EQ(1, message.map_int32_enum().size());
- EXPECT_EQ(1, message.map_int32_foreign_message().size());
-
- EXPECT_EQ(0, message.map_int32_int32().at(0));
- EXPECT_EQ(0, message.map_int64_int64().at(0));
- EXPECT_EQ(0, message.map_uint32_uint32().at(0));
- EXPECT_EQ(0, message.map_uint64_uint64().at(0));
- EXPECT_EQ(0, message.map_sint32_sint32().at(0));
- EXPECT_EQ(0, message.map_sint64_sint64().at(0));
- EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
- EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
- EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
- EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
- EXPECT_EQ(0, message.map_int32_float().at(0));
- EXPECT_EQ(0, message.map_int32_double().at(0));
- EXPECT_EQ(false, message.map_bool_bool().at(0));
- EXPECT_EQ("", message.map_string_string().at("0"));
- EXPECT_EQ("", message.map_int32_bytes().at(0));
- EXPECT_EQ(unittest::MAP_ENUM_FOO, message.map_int32_enum().at(0));
- EXPECT_EQ(0, message.map_int32_foreign_message().at(0).ByteSize());
+ MapTestUtilImpl::ExpectMapFieldsSetInitialized<unittest::MapEnum,
+ unittest::MAP_ENUM_FOO>(
+ message);
}
void MapTestUtil::ExpectMapFieldsModified(
const unittest::TestMap& message) {
- // ModifyMapFields only sets the second element of each field. In addition to
- // verifying this, we also verify that the first element and size were *not*
- // modified.
- EXPECT_EQ(2, message.map_int32_int32().size());
- EXPECT_EQ(2, message.map_int64_int64().size());
- EXPECT_EQ(2, message.map_uint32_uint32().size());
- EXPECT_EQ(2, message.map_uint64_uint64().size());
- EXPECT_EQ(2, message.map_sint32_sint32().size());
- EXPECT_EQ(2, message.map_sint64_sint64().size());
- EXPECT_EQ(2, message.map_fixed32_fixed32().size());
- EXPECT_EQ(2, message.map_fixed64_fixed64().size());
- EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
- EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
- EXPECT_EQ(2, message.map_int32_float().size());
- EXPECT_EQ(2, message.map_int32_double().size());
- EXPECT_EQ(2, message.map_bool_bool().size());
- EXPECT_EQ(2, message.map_string_string().size());
- EXPECT_EQ(2, message.map_int32_bytes().size());
- EXPECT_EQ(2, message.map_int32_enum().size());
- EXPECT_EQ(2, message.map_int32_foreign_message().size());
-
- EXPECT_EQ(0, message.map_int32_int32().at(0));
- EXPECT_EQ(0, message.map_int64_int64().at(0));
- EXPECT_EQ(0, message.map_uint32_uint32().at(0));
- EXPECT_EQ(0, message.map_uint64_uint64().at(0));
- EXPECT_EQ(0, message.map_sint32_sint32().at(0));
- EXPECT_EQ(0, message.map_sint64_sint64().at(0));
- EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
- EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
- EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
- EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
- EXPECT_EQ(0, message.map_int32_float().at(0));
- EXPECT_EQ(0, message.map_int32_double().at(0));
- EXPECT_EQ(false, message.map_bool_bool().at(0));
- EXPECT_EQ("0", message.map_string_string().at("0"));
- EXPECT_EQ("0", message.map_int32_bytes().at(0));
- EXPECT_EQ(unittest::MAP_ENUM_BAR, message.map_int32_enum().at(0));
- EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
-
- // Actually verify the second (modified) elements now.
- EXPECT_EQ(2, message.map_int32_int32().at(1));
- EXPECT_EQ(2, message.map_int64_int64().at(1));
- EXPECT_EQ(2, message.map_uint32_uint32().at(1));
- EXPECT_EQ(2, message.map_uint64_uint64().at(1));
- EXPECT_EQ(2, message.map_sint32_sint32().at(1));
- EXPECT_EQ(2, message.map_sint64_sint64().at(1));
- EXPECT_EQ(2, message.map_fixed32_fixed32().at(1));
- EXPECT_EQ(2, message.map_fixed64_fixed64().at(1));
- EXPECT_EQ(2, message.map_sfixed32_sfixed32().at(1));
- EXPECT_EQ(2, message.map_sfixed64_sfixed64().at(1));
- EXPECT_EQ(2, message.map_int32_float().at(1));
- EXPECT_EQ(2, message.map_int32_double().at(1));
- EXPECT_EQ(false, message.map_bool_bool().at(1));
- EXPECT_EQ("2", message.map_string_string().at("1"));
- EXPECT_EQ("2", message.map_int32_bytes().at(1));
- EXPECT_EQ(unittest::MAP_ENUM_FOO, message.map_int32_enum().at(1));
- EXPECT_EQ(2, message.map_int32_foreign_message().at(1).c());
+ MapTestUtilImpl::ExpectMapFieldsModified<
+ unittest::MapEnum, unittest::MAP_ENUM_BAR, unittest::MAP_ENUM_FOO>(
+ message);
}
void MapTestUtil::ExpectMapsSize(
@@ -1468,8 +1253,9 @@ void MapTestUtil::MapReflectionTester::ExpectMapEntryClearViaReflection(
sub_message = reflection->AddMessage(message, F("map_int32_enum"));
EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
key_descriptor));
- EXPECT_EQ(0, sub_message->GetReflection()->GetEnum(*sub_message,
- value_descriptor));
+ EXPECT_EQ(0, sub_message->GetReflection()
+ ->GetEnum(*sub_message, value_descriptor)
+ ->number());
}
// Map using message as value has been tested in other place. Thus, we don't
// test it here.
diff --git a/src/google/protobuf/map_test_util.h b/src/google/protobuf/map_test_util.h
index 653cf107..f437e33e 100644
--- a/src/google/protobuf/map_test_util.h
+++ b/src/google/protobuf/map_test_util.h
@@ -40,9 +40,12 @@ namespace unittest = ::protobuf_unittest;
class MapTestUtil {
public:
- // Set every field in the message to a unique value.
+ // Set every field in the TestMap message to a unique value.
static void SetMapFields(unittest::TestMap* message);
+ // Set every field in the TestArenaMap message to a unique value.
+ static void SetArenaMapFields(unittest::TestArenaMap* message);
+
// Set every field in the message to a default value.
static void SetMapFieldsInitialized(unittest::TestMap* message);
@@ -55,6 +58,10 @@ class MapTestUtil {
static void ExpectMapFieldsSet(const unittest::TestMap& message);
// Check that all fields have the values that they should have after
+ // SetMapFields() is called for TestArenaMap.
+ static void ExpectArenaMapFieldsSet(const unittest::TestArenaMap& message);
+
+ // Check that all fields have the values that they should have after
// SetMapFieldsInitialized() is called.
static void ExpectMapFieldsSetInitialized(
const unittest::TestMap& message);
diff --git a/src/google/protobuf/map_test_util_impl.h b/src/google/protobuf/map_test_util_impl.h
new file mode 100644
index 00000000..5e7882a1
--- /dev/null
+++ b/src/google/protobuf/map_test_util_impl.h
@@ -0,0 +1,474 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__
+#define GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__
+
+#include <google/protobuf/stubs/common.h>
+
+
+#define EXPECT_TRUE GOOGLE_CHECK
+#define ASSERT_TRUE GOOGLE_CHECK
+#define EXPECT_FALSE(COND) GOOGLE_CHECK(!(COND))
+#define EXPECT_EQ GOOGLE_CHECK_EQ
+#define ASSERT_EQ GOOGLE_CHECK_EQ
+
+namespace google {
+namespace protobuf_unittest {} // forward declaration
+
+namespace protobuf {
+
+namespace unittest = ::protobuf_unittest;
+
+class MapTestUtilImpl {
+ public:
+ // Set every field in the TestMap message to a unique value.
+ template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+ static void SetMapFields(MapMessage* message);
+
+ // Set every field in the TestArenaMap message to a unique value.
+ template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+ static void SetArenaMapFields(MapMessage* message);
+
+ // Set every field in the message to a default value.
+ template <typename MapMessage>
+ static void SetMapFieldsInitialized(MapMessage* message);
+
+ // Modify all the map fields of the messsage (which should already have been
+ // initialized with SetMapFields()).
+ template <typename EnumType, EnumType enum_value, typename MapMessage>
+ static void ModifyMapFields(MapMessage* message);
+
+ // Check that all fields have the values that they should have after
+ // SetMapFields() is called.
+ template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+ static void ExpectMapFieldsSet(const MapMessage& message);
+
+ // Check that all fields have the values that they should have after
+ // SetMapFields() is called for TestArenaMap.
+ template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+ static void ExpectArenaMapFieldsSet(const MapMessage& message);
+
+ // Check that all fields have the values that they should have after
+ // SetMapFieldsInitialized() is called.
+ template <typename EnumType, EnumType enum_value, typename MapMessage>
+ static void ExpectMapFieldsSetInitialized(const MapMessage& message);
+
+ // Expect that the message is modified as would be expected from
+ // ModifyMapFields().
+ template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+ static void ExpectMapFieldsModified(const MapMessage& message);
+
+ // Check that all fields are empty.
+ template <typename MapMessage>
+ static void ExpectClear(const MapMessage& message);
+
+ // // Check that all map fields have the given size.
+ // template <typename MapMessage>
+ // static void ExpectMapsSize(const MapMessage& message, int size);
+
+ // // Get pointers of map entries at given index.
+ // static std::vector<const Message*> GetMapEntries(
+ // const MapMessage& message, int index);
+
+ // // Get pointers of map entries from release.
+ // static std::vector<const Message*> GetMapEntriesFromRelease(
+ // MapMessage* message);
+};
+
+template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::SetMapFields(MapMessage* message) {
+ // Add first element.
+ (*message->mutable_map_int32_int32())[0] = 0;
+ (*message->mutable_map_int64_int64())[0] = 0;
+ (*message->mutable_map_uint32_uint32())[0] = 0;
+ (*message->mutable_map_uint64_uint64())[0] = 0;
+ (*message->mutable_map_sint32_sint32())[0] = 0;
+ (*message->mutable_map_sint64_sint64())[0] = 0;
+ (*message->mutable_map_fixed32_fixed32())[0] = 0;
+ (*message->mutable_map_fixed64_fixed64())[0] = 0;
+ (*message->mutable_map_sfixed32_sfixed32())[0] = 0;
+ (*message->mutable_map_sfixed64_sfixed64())[0] = 0;
+ (*message->mutable_map_int32_float())[0] = 0.0;
+ (*message->mutable_map_int32_double())[0] = 0.0;
+ (*message->mutable_map_bool_bool())[0] = false;
+ (*message->mutable_map_string_string())["0"] = "0";
+ (*message->mutable_map_int32_bytes())[0] = "0";
+ (*message->mutable_map_int32_enum())[0] = enum_value0;
+ (*message->mutable_map_int32_foreign_message())[0].set_c(0);
+
+ // Add second element
+ (*message->mutable_map_int32_int32())[1] = 1;
+ (*message->mutable_map_int64_int64())[1] = 1;
+ (*message->mutable_map_uint32_uint32())[1] = 1;
+ (*message->mutable_map_uint64_uint64())[1] = 1;
+ (*message->mutable_map_sint32_sint32())[1] = 1;
+ (*message->mutable_map_sint64_sint64())[1] = 1;
+ (*message->mutable_map_fixed32_fixed32())[1] = 1;
+ (*message->mutable_map_fixed64_fixed64())[1] = 1;
+ (*message->mutable_map_sfixed32_sfixed32())[1] = 1;
+ (*message->mutable_map_sfixed64_sfixed64())[1] = 1;
+ (*message->mutable_map_int32_float())[1] = 1.0;
+ (*message->mutable_map_int32_double())[1] = 1.0;
+ (*message->mutable_map_bool_bool())[1] = true;
+ (*message->mutable_map_string_string())["1"] = "1";
+ (*message->mutable_map_int32_bytes())[1] = "1";
+ (*message->mutable_map_int32_enum())[1] = enum_value1;
+ (*message->mutable_map_int32_foreign_message())[1].set_c(1);
+}
+
+template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::SetArenaMapFields(MapMessage* message) {
+ // Add first element.
+ (*message->mutable_map_int32_int32())[0] = 0;
+ (*message->mutable_map_int64_int64())[0] = 0;
+ (*message->mutable_map_uint32_uint32())[0] = 0;
+ (*message->mutable_map_uint64_uint64())[0] = 0;
+ (*message->mutable_map_sint32_sint32())[0] = 0;
+ (*message->mutable_map_sint64_sint64())[0] = 0;
+ (*message->mutable_map_fixed32_fixed32())[0] = 0;
+ (*message->mutable_map_fixed64_fixed64())[0] = 0;
+ (*message->mutable_map_sfixed32_sfixed32())[0] = 0;
+ (*message->mutable_map_sfixed64_sfixed64())[0] = 0;
+ (*message->mutable_map_int32_float())[0] = 0.0;
+ (*message->mutable_map_int32_double())[0] = 0.0;
+ (*message->mutable_map_bool_bool())[0] = false;
+ (*message->mutable_map_int32_enum())[0] = enum_value0;
+ (*message->mutable_map_int32_foreign_message())[0].set_c(0);
+
+ // Add second element
+ (*message->mutable_map_int32_int32())[1] = 1;
+ (*message->mutable_map_int64_int64())[1] = 1;
+ (*message->mutable_map_uint32_uint32())[1] = 1;
+ (*message->mutable_map_uint64_uint64())[1] = 1;
+ (*message->mutable_map_sint32_sint32())[1] = 1;
+ (*message->mutable_map_sint64_sint64())[1] = 1;
+ (*message->mutable_map_fixed32_fixed32())[1] = 1;
+ (*message->mutable_map_fixed64_fixed64())[1] = 1;
+ (*message->mutable_map_sfixed32_sfixed32())[1] = 1;
+ (*message->mutable_map_sfixed64_sfixed64())[1] = 1;
+ (*message->mutable_map_int32_float())[1] = 1.0;
+ (*message->mutable_map_int32_double())[1] = 1.0;
+ (*message->mutable_map_bool_bool())[1] = true;
+ (*message->mutable_map_int32_enum())[1] = enum_value1;
+ (*message->mutable_map_int32_foreign_message())[1].set_c(1);
+}
+
+template <typename MapMessage>
+void MapTestUtilImpl::SetMapFieldsInitialized(MapMessage* message) {
+ // Add first element using bracket operator, which should assign default
+ // value automatically.
+ (*message->mutable_map_int32_int32())[0];
+ (*message->mutable_map_int64_int64())[0];
+ (*message->mutable_map_uint32_uint32())[0];
+ (*message->mutable_map_uint64_uint64())[0];
+ (*message->mutable_map_sint32_sint32())[0];
+ (*message->mutable_map_sint64_sint64())[0];
+ (*message->mutable_map_fixed32_fixed32())[0];
+ (*message->mutable_map_fixed64_fixed64())[0];
+ (*message->mutable_map_sfixed32_sfixed32())[0];
+ (*message->mutable_map_sfixed64_sfixed64())[0];
+ (*message->mutable_map_int32_float())[0];
+ (*message->mutable_map_int32_double())[0];
+ (*message->mutable_map_bool_bool())[0];
+ (*message->mutable_map_string_string())["0"];
+ (*message->mutable_map_int32_bytes())[0];
+ (*message->mutable_map_int32_enum())[0];
+ (*message->mutable_map_int32_foreign_message())[0];
+}
+
+template <typename EnumType, EnumType enum_value, typename MapMessage>
+void MapTestUtilImpl::ModifyMapFields(MapMessage* message) {
+ (*message->mutable_map_int32_int32())[1] = 2;
+ (*message->mutable_map_int64_int64())[1] = 2;
+ (*message->mutable_map_uint32_uint32())[1] = 2;
+ (*message->mutable_map_uint64_uint64())[1] = 2;
+ (*message->mutable_map_sint32_sint32())[1] = 2;
+ (*message->mutable_map_sint64_sint64())[1] = 2;
+ (*message->mutable_map_fixed32_fixed32())[1] = 2;
+ (*message->mutable_map_fixed64_fixed64())[1] = 2;
+ (*message->mutable_map_sfixed32_sfixed32())[1] = 2;
+ (*message->mutable_map_sfixed64_sfixed64())[1] = 2;
+ (*message->mutable_map_int32_float())[1] = 2.0;
+ (*message->mutable_map_int32_double())[1] = 2.0;
+ (*message->mutable_map_bool_bool())[1] = false;
+ (*message->mutable_map_string_string())["1"] = "2";
+ (*message->mutable_map_int32_bytes())[1] = "2";
+ (*message->mutable_map_int32_enum())[1] = enum_value;
+ (*message->mutable_map_int32_foreign_message())[1].set_c(2);
+}
+
+template <typename MapMessage>
+void MapTestUtilImpl::ExpectClear(const MapMessage& message) {
+ EXPECT_EQ(0, message.map_int32_int32().size());
+ EXPECT_EQ(0, message.map_int64_int64().size());
+ EXPECT_EQ(0, message.map_uint32_uint32().size());
+ EXPECT_EQ(0, message.map_uint64_uint64().size());
+ EXPECT_EQ(0, message.map_sint32_sint32().size());
+ EXPECT_EQ(0, message.map_sint64_sint64().size());
+ EXPECT_EQ(0, message.map_fixed32_fixed32().size());
+ EXPECT_EQ(0, message.map_fixed64_fixed64().size());
+ EXPECT_EQ(0, message.map_sfixed32_sfixed32().size());
+ EXPECT_EQ(0, message.map_sfixed64_sfixed64().size());
+ EXPECT_EQ(0, message.map_int32_float().size());
+ EXPECT_EQ(0, message.map_int32_double().size());
+ EXPECT_EQ(0, message.map_bool_bool().size());
+ EXPECT_EQ(0, message.map_string_string().size());
+ EXPECT_EQ(0, message.map_int32_bytes().size());
+ EXPECT_EQ(0, message.map_int32_enum().size());
+ EXPECT_EQ(0, message.map_int32_foreign_message().size());
+}
+
+
+
+template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::ExpectMapFieldsSet(const MapMessage& message) {
+ EXPECT_EQ(2, message.map_int32_int32().size());
+ EXPECT_EQ(2, message.map_int64_int64().size());
+ EXPECT_EQ(2, message.map_uint32_uint32().size());
+ EXPECT_EQ(2, message.map_uint64_uint64().size());
+ EXPECT_EQ(2, message.map_sint32_sint32().size());
+ EXPECT_EQ(2, message.map_sint64_sint64().size());
+ EXPECT_EQ(2, message.map_fixed32_fixed32().size());
+ EXPECT_EQ(2, message.map_fixed64_fixed64().size());
+ EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
+ EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
+ EXPECT_EQ(2, message.map_int32_float().size());
+ EXPECT_EQ(2, message.map_int32_double().size());
+ EXPECT_EQ(2, message.map_bool_bool().size());
+ EXPECT_EQ(2, message.map_string_string().size());
+ EXPECT_EQ(2, message.map_int32_bytes().size());
+ EXPECT_EQ(2, message.map_int32_enum().size());
+ EXPECT_EQ(2, message.map_int32_foreign_message().size());
+
+ EXPECT_EQ(0, message.map_int32_int32().at(0));
+ EXPECT_EQ(0, message.map_int64_int64().at(0));
+ EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+ EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+ EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+ EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+ EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+ EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+ EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+ EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+ EXPECT_EQ(0, message.map_int32_float().at(0));
+ EXPECT_EQ(0, message.map_int32_double().at(0));
+ EXPECT_EQ(false, message.map_bool_bool().at(0));
+ EXPECT_EQ("0", message.map_string_string().at("0"));
+ EXPECT_EQ("0", message.map_int32_bytes().at(0));
+ EXPECT_EQ(enum_value0, message.map_int32_enum().at(0));
+ EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
+
+ EXPECT_EQ(1, message.map_int32_int32().at(1));
+ EXPECT_EQ(1, message.map_int64_int64().at(1));
+ EXPECT_EQ(1, message.map_uint32_uint32().at(1));
+ EXPECT_EQ(1, message.map_uint64_uint64().at(1));
+ EXPECT_EQ(1, message.map_sint32_sint32().at(1));
+ EXPECT_EQ(1, message.map_sint64_sint64().at(1));
+ EXPECT_EQ(1, message.map_fixed32_fixed32().at(1));
+ EXPECT_EQ(1, message.map_fixed64_fixed64().at(1));
+ EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1));
+ EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1));
+ EXPECT_EQ(1, message.map_int32_float().at(1));
+ EXPECT_EQ(1, message.map_int32_double().at(1));
+ EXPECT_EQ(true, message.map_bool_bool().at(1));
+ EXPECT_EQ("1", message.map_string_string().at("1"));
+ EXPECT_EQ("1", message.map_int32_bytes().at(1));
+ EXPECT_EQ(enum_value1, message.map_int32_enum().at(1));
+ EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c());
+}
+
+template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) {
+ EXPECT_EQ(2, message.map_int32_int32().size());
+ EXPECT_EQ(2, message.map_int64_int64().size());
+ EXPECT_EQ(2, message.map_uint32_uint32().size());
+ EXPECT_EQ(2, message.map_uint64_uint64().size());
+ EXPECT_EQ(2, message.map_sint32_sint32().size());
+ EXPECT_EQ(2, message.map_sint64_sint64().size());
+ EXPECT_EQ(2, message.map_fixed32_fixed32().size());
+ EXPECT_EQ(2, message.map_fixed64_fixed64().size());
+ EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
+ EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
+ EXPECT_EQ(2, message.map_int32_float().size());
+ EXPECT_EQ(2, message.map_int32_double().size());
+ EXPECT_EQ(2, message.map_bool_bool().size());
+ EXPECT_EQ(2, message.map_int32_enum().size());
+ EXPECT_EQ(2, message.map_int32_foreign_message().size());
+
+ EXPECT_EQ(0, message.map_int32_int32().at(0));
+ EXPECT_EQ(0, message.map_int64_int64().at(0));
+ EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+ EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+ EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+ EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+ EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+ EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+ EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+ EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+ EXPECT_EQ(0, message.map_int32_float().at(0));
+ EXPECT_EQ(0, message.map_int32_double().at(0));
+ EXPECT_EQ(false, message.map_bool_bool().at(0));
+ EXPECT_EQ(enum_value0, message.map_int32_enum().at(0));
+ EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
+
+ EXPECT_EQ(1, message.map_int32_int32().at(1));
+ EXPECT_EQ(1, message.map_int64_int64().at(1));
+ EXPECT_EQ(1, message.map_uint32_uint32().at(1));
+ EXPECT_EQ(1, message.map_uint64_uint64().at(1));
+ EXPECT_EQ(1, message.map_sint32_sint32().at(1));
+ EXPECT_EQ(1, message.map_sint64_sint64().at(1));
+ EXPECT_EQ(1, message.map_fixed32_fixed32().at(1));
+ EXPECT_EQ(1, message.map_fixed64_fixed64().at(1));
+ EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1));
+ EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1));
+ EXPECT_EQ(1, message.map_int32_float().at(1));
+ EXPECT_EQ(1, message.map_int32_double().at(1));
+ EXPECT_EQ(true, message.map_bool_bool().at(1));
+ EXPECT_EQ(enum_value1, message.map_int32_enum().at(1));
+ EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c());
+}
+
+template <typename EnumType, EnumType enum_value, typename MapMessage>
+void MapTestUtilImpl::ExpectMapFieldsSetInitialized(
+ const MapMessage& message) {
+ EXPECT_EQ(1, message.map_int32_int32().size());
+ EXPECT_EQ(1, message.map_int64_int64().size());
+ EXPECT_EQ(1, message.map_uint32_uint32().size());
+ EXPECT_EQ(1, message.map_uint64_uint64().size());
+ EXPECT_EQ(1, message.map_sint32_sint32().size());
+ EXPECT_EQ(1, message.map_sint64_sint64().size());
+ EXPECT_EQ(1, message.map_fixed32_fixed32().size());
+ EXPECT_EQ(1, message.map_fixed64_fixed64().size());
+ EXPECT_EQ(1, message.map_sfixed32_sfixed32().size());
+ EXPECT_EQ(1, message.map_sfixed64_sfixed64().size());
+ EXPECT_EQ(1, message.map_int32_float().size());
+ EXPECT_EQ(1, message.map_int32_double().size());
+ EXPECT_EQ(1, message.map_bool_bool().size());
+ EXPECT_EQ(1, message.map_string_string().size());
+ EXPECT_EQ(1, message.map_int32_bytes().size());
+ EXPECT_EQ(1, message.map_int32_enum().size());
+ EXPECT_EQ(1, message.map_int32_foreign_message().size());
+
+ EXPECT_EQ(0, message.map_int32_int32().at(0));
+ EXPECT_EQ(0, message.map_int64_int64().at(0));
+ EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+ EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+ EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+ EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+ EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+ EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+ EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+ EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+ EXPECT_EQ(0, message.map_int32_float().at(0));
+ EXPECT_EQ(0, message.map_int32_double().at(0));
+ EXPECT_EQ(false, message.map_bool_bool().at(0));
+ EXPECT_EQ("", message.map_string_string().at("0"));
+ EXPECT_EQ("", message.map_int32_bytes().at(0));
+ EXPECT_EQ(enum_value, message.map_int32_enum().at(0));
+ EXPECT_EQ(0, message.map_int32_foreign_message().at(0).ByteSize());
+}
+
+template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::ExpectMapFieldsModified(
+ const MapMessage& message) {
+ // ModifyMapFields only sets the second element of each field. In addition to
+ // verifying this, we also verify that the first element and size were *not*
+ // modified.
+ EXPECT_EQ(2, message.map_int32_int32().size());
+ EXPECT_EQ(2, message.map_int64_int64().size());
+ EXPECT_EQ(2, message.map_uint32_uint32().size());
+ EXPECT_EQ(2, message.map_uint64_uint64().size());
+ EXPECT_EQ(2, message.map_sint32_sint32().size());
+ EXPECT_EQ(2, message.map_sint64_sint64().size());
+ EXPECT_EQ(2, message.map_fixed32_fixed32().size());
+ EXPECT_EQ(2, message.map_fixed64_fixed64().size());
+ EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
+ EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
+ EXPECT_EQ(2, message.map_int32_float().size());
+ EXPECT_EQ(2, message.map_int32_double().size());
+ EXPECT_EQ(2, message.map_bool_bool().size());
+ EXPECT_EQ(2, message.map_string_string().size());
+ EXPECT_EQ(2, message.map_int32_bytes().size());
+ EXPECT_EQ(2, message.map_int32_enum().size());
+ EXPECT_EQ(2, message.map_int32_foreign_message().size());
+
+ EXPECT_EQ(0, message.map_int32_int32().at(0));
+ EXPECT_EQ(0, message.map_int64_int64().at(0));
+ EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+ EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+ EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+ EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+ EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+ EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+ EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+ EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+ EXPECT_EQ(0, message.map_int32_float().at(0));
+ EXPECT_EQ(0, message.map_int32_double().at(0));
+ EXPECT_EQ(false, message.map_bool_bool().at(0));
+ EXPECT_EQ("0", message.map_string_string().at("0"));
+ EXPECT_EQ("0", message.map_int32_bytes().at(0));
+ EXPECT_EQ(enum_value0, message.map_int32_enum().at(0));
+ EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
+
+ // Actually verify the second (modified) elements now.
+ EXPECT_EQ(2, message.map_int32_int32().at(1));
+ EXPECT_EQ(2, message.map_int64_int64().at(1));
+ EXPECT_EQ(2, message.map_uint32_uint32().at(1));
+ EXPECT_EQ(2, message.map_uint64_uint64().at(1));
+ EXPECT_EQ(2, message.map_sint32_sint32().at(1));
+ EXPECT_EQ(2, message.map_sint64_sint64().at(1));
+ EXPECT_EQ(2, message.map_fixed32_fixed32().at(1));
+ EXPECT_EQ(2, message.map_fixed64_fixed64().at(1));
+ EXPECT_EQ(2, message.map_sfixed32_sfixed32().at(1));
+ EXPECT_EQ(2, message.map_sfixed64_sfixed64().at(1));
+ EXPECT_EQ(2, message.map_int32_float().at(1));
+ EXPECT_EQ(2, message.map_int32_double().at(1));
+ EXPECT_EQ(false, message.map_bool_bool().at(1));
+ EXPECT_EQ("2", message.map_string_string().at("1"));
+ EXPECT_EQ("2", message.map_int32_bytes().at(1));
+ EXPECT_EQ(enum_value1, message.map_int32_enum().at(1));
+ EXPECT_EQ(2, message.map_int32_foreign_message().at(1).c());
+}
+
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__
diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h
index 88a6d7b8..ffdb6dfb 100644
--- a/src/google/protobuf/map_type_handler.h
+++ b/src/google/protobuf/map_type_handler.h
@@ -31,8 +31,8 @@
#ifndef GOOGLE_PROTOBUF_TYPE_HANDLER_H__
#define GOOGLE_PROTOBUF_TYPE_HANDLER_H__
+#include <google/protobuf/arena.h>
#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/message.h>
#include <google/protobuf/wire_format_lite_inl.h>
namespace google {
@@ -92,6 +92,28 @@ class MapValueInitializer<false, Type> {
static inline void Initialize(Type& value, int default_enum_value) {}
};
+template <typename Type, bool is_arena_constructable>
+class MapArenaMessageCreator {
+ public:
+ // Use arena to create message if Type is arena constructable. Otherwise,
+ // create the message on heap.
+ static inline Type* CreateMessage(Arena* arena);
+};
+template <typename Type>
+class MapArenaMessageCreator<Type, true> {
+ public:
+ static inline Type* CreateMessage(Arena* arena) {
+ return Arena::CreateMessage<Type>(arena);
+ }
+};
+template <typename Type>
+class MapArenaMessageCreator<Type, false> {
+ public:
+ static inline Type* CreateMessage(Arena* arena) {
+ return new Type;
+ }
+};
+
// Handlers for key/value stored type in MapField. ==================
// Handler for message
@@ -107,11 +129,11 @@ class MapCppTypeHandler : public MapCommonTypeHandler<Type> {
// Return bytes used by value in Map.
static int SpaceUsedInMap(const Type& value) { return value.SpaceUsed(); }
static inline void Clear(Type** value) {
- if (*value != NULL) (*value)->Type::Clear();
+ if (*value != NULL) (*value)->Clear();
}
static inline void ClearMaybeByDefaultEnum(Type** value,
int default_enum_value) {
- if (*value != NULL) (*value)->Type::Clear();
+ if (*value != NULL) (*value)->Clear();
}
static inline void Merge(const Type& from, Type** to) {
(*to)->MergeFrom(from);
@@ -124,20 +146,24 @@ class MapCppTypeHandler : public MapCommonTypeHandler<Type> {
*value = const_cast<Type*>(&Type::default_instance());
}
// Initialize value when constructing MapEntry
- static inline void Initialize(Type** x) { *x = NULL; }
+ static inline void Initialize(Type** x, Arena* arena) { *x = NULL; }
// Same as above, but use default_enum_value to initialize enum type value.
static inline void InitializeMaybeByDefaultEnum(
- Type** x, int default_enum_value) {
+ Type** x, int default_enum_value, Arena* arena) {
*x = NULL;
}
// Initialize value for the first time mutable accessor is called.
- static inline void EnsureMutable(Type** value) {
- if (*value == NULL) *value = new Type;
+ static inline void EnsureMutable(Type** value, Arena* arena) {
+ if (*value == NULL) {
+ *value =
+ MapArenaMessageCreator<Type, Arena::is_arena_constructable<Type>::
+ type::value>::CreateMessage(arena);
+ }
}
// Return default instance if value is not initialized when calling const
// reference accessor.
- static inline const Type& DefaultIfNotInitialized(Type* value,
- Type* default_value) {
+ static inline const Type& DefaultIfNotInitialized(const Type* value,
+ const Type* default_value) {
return value != NULL ? *value : *default_value;
}
// Check if all required fields have values set.
@@ -166,18 +192,23 @@ class MapCppTypeHandler<string> : public MapCommonTypeHandler<string> {
if (ptr != &::google::protobuf::internal::GetEmptyString()) delete ptr;
}
static inline void AssignDefaultValue(string** value) {}
- static inline void Initialize(string** value) {
+ static inline void Initialize(string** value, Arena* arena) {
*value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ if (arena != NULL) arena->Own(*value);
}
static inline void InitializeMaybeByDefaultEnum(
- string** value, int default_enum_value) {
+ string** value, int default_enum_value, Arena* arena) {
*value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ if (arena != NULL) arena->Own(*value);
}
- static inline void EnsureMutable(string** value) {
- if (*value == &::google::protobuf::internal::GetEmptyString()) *value = new string;
+ static inline void EnsureMutable(string** value, Arena* arena) {
+ if (*value == &::google::protobuf::internal::GetEmptyString()) {
+ *value = Arena::Create<string>(arena);
+ }
}
- static inline const string& DefaultIfNotInitialized(string* value,
- string* default_value) {
+ static inline const string& DefaultIfNotInitialized(
+ const string* value,
+ const string* default_value) {
return value != default_value ? *value : *default_value;
}
static inline bool IsInitialized(string* value) { return true; }
@@ -210,12 +241,13 @@ class MapPrimitiveTypeHandler : public MapCommonTypeHandler<Type> {
int default_enum_value) { \
*value = static_cast<CType>(default_enum_value); \
} \
- static inline void Initialize(CType* value) { *value = 0; } \
+ static inline void Initialize(CType* value, Arena* arena) { *value = 0; } \
static inline void InitializeMaybeByDefaultEnum(CType* value, \
- int default_enum_value) { \
+ int default_enum_value, \
+ Arena* arena) { \
*value = static_cast<CType>(default_enum_value); \
} \
- static inline void EnsureMutable(CType* value) {} \
+ static inline void EnsureMutable(CType* value, Arena* arena) {} \
};
PRIMITIVE_HANDLER(int32 )
@@ -228,13 +260,13 @@ PRIMITIVE_HANDLER(bool )
#undef PRIMITIVE_HANDLER
-// Define constants for given proto field type
-template <FieldDescriptor::Type Type>
-class MapFieldTypeTraits {};
+// Define constants for given wire field type
+template <WireFormatLite::FieldType field_type>
+class MapWireFieldTypeTraits {};
#define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \
template <> \
- class MapFieldTypeTraits<FieldDescriptor::TYPE_##FieldType> { \
+ class MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType> { \
public: \
typedef CType CppType; \
static const bool kIsMessage = IsMessage; \
@@ -243,7 +275,7 @@ class MapFieldTypeTraits {};
WireFormatLite::WIRETYPE_##WireFormatType; \
};
-TYPE_TRAITS(MESSAGE , Message, LENGTH_DELIMITED, true, false)
+TYPE_TRAITS(MESSAGE , MessageLite, LENGTH_DELIMITED, true, false)
TYPE_TRAITS(STRING , string , LENGTH_DELIMITED, false, false)
TYPE_TRAITS(BYTES , string , LENGTH_DELIMITED, false, false)
TYPE_TRAITS(INT64 , int64 , VARINT , false, false)
@@ -263,51 +295,46 @@ TYPE_TRAITS(BOOL , bool , VARINT , false, false)
#undef TYPE_TRAITS
-// Handler for proto field type. Define types and constants used in compile
-// time. Also define functions used in parsing and serializing.
-template <FieldDescriptor::Type Type>
-class MapProtoTypeHandler {
+template <WireFormatLite::FieldType field_type>
+class MapWireFieldTypeHandler {
public:
- // Internal stored type in MapEntry for given proto field type.
- typedef typename MapFieldTypeTraits<Type>::CppType CppType;
-
- // Whether given type is a message.
- static const bool kIsMessage = MapFieldTypeTraits<Type>::kIsMessage;
-
- // Whether given type is an enum.
- static const bool kIsEnum = MapFieldTypeTraits<Type>::kIsEnum;
-
- // The wire type of given proto field type.
+ // Internal stored type in MapEntryLite for given wire field type.
+ typedef typename MapWireFieldTypeTraits<field_type>::CppType CppType;
+ // Corresponding wire type for field type.
static const WireFormatLite::WireType kWireType =
- MapFieldTypeTraits<Type>::kWireType;
+ MapWireFieldTypeTraits<field_type>::kWireType;
+ // Whether wire type is for message.
+ static const bool kIsMessage = MapWireFieldTypeTraits<field_type>::kIsMessage;
+ // Whether wire type is for enum.
+ static const bool kIsEnum = MapWireFieldTypeTraits<field_type>::kIsEnum;
// Functions used in parsing and serialization. ===================
-
template <typename ValueType>
static inline int ByteSize(const ValueType& value);
template <typename ValueType>
static inline int GetCachedSize(const ValueType& value);
+ template <typename ValueType>
+ static inline bool Read(io::CodedInputStream* input, ValueType* value);
static inline void Write(int field, const CppType& value,
io::CodedOutputStream* output);
static inline uint8* WriteToArray(int field, const CppType& value,
uint8* output);
- template <typename ValueType>
- static inline bool Read(io::CodedInputStream* input, ValueType* value);
};
template <>
template <typename ValueType>
-inline int MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::ByteSize(
+inline int MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::ByteSize(
const ValueType& value) {
return WireFormatLite::MessageSizeNoVirtual(value);
}
-#define BYTE_SIZE(FieldType, DeclaredType) \
- template <> \
- template <typename ValueType> \
- inline int MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::ByteSize( \
- const ValueType& value) { \
- return WireFormatLite::DeclaredType##Size(value); \
+#define BYTE_SIZE(FieldType, DeclaredType) \
+ template <> \
+ template <typename ValueType> \
+ inline int \
+ MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::ByteSize( \
+ const ValueType& value) { \
+ return WireFormatLite::DeclaredType##Size(value); \
}
BYTE_SIZE(STRING, String)
@@ -322,12 +349,13 @@ BYTE_SIZE(ENUM , Enum)
#undef BYTE_SIZE
-#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \
- template <> \
- template <typename ValueType> \
- inline int MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::ByteSize( \
- const ValueType& value) { \
- return WireFormatLite::k##DeclaredType##Size; \
+#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \
+ template <> \
+ template <typename ValueType> \
+ inline int \
+ MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::ByteSize( \
+ const ValueType& value) { \
+ return WireFormatLite::k##DeclaredType##Size; \
}
FIXED_BYTE_SIZE(DOUBLE , Double)
@@ -342,18 +370,18 @@ FIXED_BYTE_SIZE(BOOL , Bool)
template <>
template <typename ValueType>
-inline int MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::GetCachedSize(
- const ValueType& value) {
+inline int MapWireFieldTypeHandler<
+ WireFormatLite::TYPE_MESSAGE>::GetCachedSize(const ValueType& value) {
return WireFormatLite::LengthDelimitedSize(value.GetCachedSize());
}
-#define GET_CACHED_SIZE(FieldType, DeclaredType) \
- template <> \
- template <typename ValueType> \
- inline int \
- MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::GetCachedSize( \
- const ValueType& value) { \
- return WireFormatLite::DeclaredType##Size(value); \
+#define GET_CACHED_SIZE(FieldType, DeclaredType) \
+ template <> \
+ template <typename ValueType> \
+ inline int \
+ MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::GetCachedSize( \
+ const ValueType& value) { \
+ return WireFormatLite::DeclaredType##Size(value); \
}
GET_CACHED_SIZE(STRING, String)
@@ -368,13 +396,13 @@ GET_CACHED_SIZE(ENUM , Enum)
#undef GET_CACHED_SIZE
-#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \
- template <> \
- template <typename ValueType> \
- inline int \
- MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::GetCachedSize( \
- const ValueType& value) { \
- return WireFormatLite::k##DeclaredType##Size; \
+#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \
+ template <> \
+ template <typename ValueType> \
+ inline int \
+ MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::GetCachedSize( \
+ const ValueType& value) { \
+ return WireFormatLite::k##DeclaredType##Size; \
}
GET_FIXED_CACHED_SIZE(DOUBLE , Double)
@@ -388,26 +416,28 @@ GET_FIXED_CACHED_SIZE(BOOL , Bool)
#undef GET_FIXED_CACHED_SIZE
template <>
-inline void MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::Write(
- int field, const Message& value, io::CodedOutputStream* output) {
+inline void MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::Write(
+ int field, const MessageLite& value, io::CodedOutputStream* output) {
WireFormatLite::WriteMessageMaybeToArray(field, value, output);
}
template <>
-inline uint8* MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::WriteToArray(
- int field, const Message& value, uint8* output) {
+inline uint8*
+MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::WriteToArray(
+ int field, const MessageLite& value, uint8* output) {
return WireFormatLite::WriteMessageToArray(field, value, output);
}
#define WRITE_METHOD(FieldType, DeclaredType) \
template <> \
- inline void MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::Write( \
+ inline void \
+ MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::Write( \
int field, const CppType& value, io::CodedOutputStream* output) { \
return WireFormatLite::Write##DeclaredType(field, value, output); \
} \
template <> \
inline uint8* \
- MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::WriteToArray( \
+ MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::WriteToArray( \
int field, const CppType& value, uint8* output) { \
return WireFormatLite::Write##DeclaredType##ToArray(field, value, output); \
}
@@ -433,33 +463,33 @@ WRITE_METHOD(BOOL , Bool)
template <>
template <typename ValueType>
-inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::Read(
+inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::Read(
io::CodedInputStream* input, ValueType* value) {
return WireFormatLite::ReadMessageNoVirtual(input, value);
}
template <>
template <typename ValueType>
-inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_STRING>::Read(
+inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_STRING>::Read(
io::CodedInputStream* input, ValueType* value) {
return WireFormatLite::ReadString(input, value);
}
template <>
template <typename ValueType>
-inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_BYTES>::Read(
+inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_BYTES>::Read(
io::CodedInputStream* input, ValueType* value) {
return WireFormatLite::ReadBytes(input, value);
}
-#define READ_METHOD(FieldType) \
- template <> \
- template <typename ValueType> \
- inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::Read( \
- io::CodedInputStream* input, ValueType* value) { \
- return WireFormatLite::ReadPrimitive<CppType, \
- WireFormatLite::TYPE_##FieldType>( \
- input, value); \
+#define READ_METHOD(FieldType) \
+ template <> \
+ template <typename ValueType> \
+ inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::Read( \
+ io::CodedInputStream* input, ValueType* value) { \
+ return WireFormatLite::ReadPrimitive<CppType, \
+ WireFormatLite::TYPE_##FieldType>( \
+ input, value); \
}
READ_METHOD(INT64)
diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto
index 9232d58f..b308c7ff 100644
--- a/src/google/protobuf/map_unittest.proto
+++ b/src/google/protobuf/map_unittest.proto
@@ -30,6 +30,7 @@
syntax = "proto3";
+option cc_enable_arenas = true;
import "google/protobuf/unittest.proto";
@@ -59,6 +60,10 @@ message TestMap {
map<int32 , ForeignMessage> map_int32_foreign_message = 17;
}
+message TestMapSubmessage {
+ TestMap test_map = 1;
+}
+
message TestMessageMap {
map<int32, TestAllTypes> map_int32_message = 1;
}
@@ -80,3 +85,35 @@ enum MapEnum {
message TestRequiredMessageMap {
map<int32, TestRequired> map_field = 1;
}
+
+message TestArenaMap {
+ map<int32 , int32 > map_int32_int32 = 1;
+ map<int64 , int64 > map_int64_int64 = 2;
+ map<uint32 , uint32 > map_uint32_uint32 = 3;
+ map<uint64 , uint64 > map_uint64_uint64 = 4;
+ map<sint32 , sint32 > map_sint32_sint32 = 5;
+ map<sint64 , sint64 > map_sint64_sint64 = 6;
+ map<fixed32 , fixed32 > map_fixed32_fixed32 = 7;
+ map<fixed64 , fixed64 > map_fixed64_fixed64 = 8;
+ map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+ map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+ map<int32 , float > map_int32_float = 11;
+ map<int32 , double > map_int32_double = 12;
+ map<bool , bool > map_bool_bool = 13;
+ map<int32 , MapEnum > map_int32_enum = 14;
+ map<int32 , ForeignMessage> map_int32_foreign_message = 15;
+}
+
+// Previously, message containing enum called Type cannot be used as value of
+// map field.
+message MessageContainingEnumCalledType {
+ enum Type {
+ TYPE_FOO = 0;
+ }
+ map<int32, MessageContainingEnumCalledType> type = 1;
+}
+
+// Previously, message cannot contain map field called "entry".
+message MessageContainingMapCalledEntry {
+ map<int32, int32> entry = 1;
+}
diff --git a/src/google/protobuf/map_unittest_proto3.proto b/src/google/protobuf/map_unittest_proto3.proto
new file mode 100644
index 00000000..16be2773
--- /dev/null
+++ b/src/google/protobuf/map_unittest_proto3.proto
@@ -0,0 +1,120 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file is mostly equivalent to map_unittest.proto, but imports
+// unittest_proto3.proto instead of unittest.proto, so that it only
+// uses proto3 messages. This makes it suitable for testing
+// implementations which only support proto3.
+// The TestRequiredMessageMap message has been removed as there are no
+// required fields in proto3.
+syntax = "proto3";
+
+option cc_enable_arenas = true;
+option csharp_namespace = "Google.Protobuf.TestProtos";
+
+import "google/protobuf/unittest_proto3.proto";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In map_test_util.h we do "using namespace unittest = protobuf_unittest".
+package protobuf_unittest;
+
+// Tests maps.
+message TestMap {
+ map<int32 , int32 > map_int32_int32 = 1;
+ map<int64 , int64 > map_int64_int64 = 2;
+ map<uint32 , uint32 > map_uint32_uint32 = 3;
+ map<uint64 , uint64 > map_uint64_uint64 = 4;
+ map<sint32 , sint32 > map_sint32_sint32 = 5;
+ map<sint64 , sint64 > map_sint64_sint64 = 6;
+ map<fixed32 , fixed32 > map_fixed32_fixed32 = 7;
+ map<fixed64 , fixed64 > map_fixed64_fixed64 = 8;
+ map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+ map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+ map<int32 , float > map_int32_float = 11;
+ map<int32 , double > map_int32_double = 12;
+ map<bool , bool > map_bool_bool = 13;
+ map<string , string > map_string_string = 14;
+ map<int32 , bytes > map_int32_bytes = 15;
+ map<int32 , MapEnum > map_int32_enum = 16;
+ map<int32 , ForeignMessage> map_int32_foreign_message = 17;
+}
+
+message TestMapSubmessage {
+ TestMap test_map = 1;
+}
+
+message TestMessageMap {
+ map<int32, TestAllTypes> map_int32_message = 1;
+}
+
+// Two map fields share the same entry default instance.
+message TestSameTypeMap {
+ map<int32, int32> map1 = 1;
+ map<int32, int32> map2 = 2;
+}
+
+enum MapEnum {
+ MAP_ENUM_FOO = 0;
+ MAP_ENUM_BAR = 1;
+ MAP_ENUM_BAZ = 2;
+}
+
+message TestArenaMap {
+ map<int32 , int32 > map_int32_int32 = 1;
+ map<int64 , int64 > map_int64_int64 = 2;
+ map<uint32 , uint32 > map_uint32_uint32 = 3;
+ map<uint64 , uint64 > map_uint64_uint64 = 4;
+ map<sint32 , sint32 > map_sint32_sint32 = 5;
+ map<sint64 , sint64 > map_sint64_sint64 = 6;
+ map<fixed32 , fixed32 > map_fixed32_fixed32 = 7;
+ map<fixed64 , fixed64 > map_fixed64_fixed64 = 8;
+ map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+ map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+ map<int32 , float > map_int32_float = 11;
+ map<int32 , double > map_int32_double = 12;
+ map<bool , bool > map_bool_bool = 13;
+ map<int32 , MapEnum > map_int32_enum = 14;
+ map<int32 , ForeignMessage> map_int32_foreign_message = 15;
+}
+
+// Previously, message containing enum called Type cannot be used as value of
+// map field.
+message MessageContainingEnumCalledType {
+ enum Type {
+ TYPE_FOO = 0;
+ }
+ map<int32, MessageContainingEnumCalledType> type = 1;
+}
+
+// Previously, message cannot contain map field called "entry".
+message MessageContainingMapCalledEntry {
+ map<int32, int32> entry = 1;
+}
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index afe95461..276d7de5 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -441,10 +441,45 @@ const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor(
}
namespace internal {
-// Macro defined in repeated_field.h. We can only define the Message-specific
-// GenericTypeHandler specializations here because we depend on Message, which
-// is not part of proto2-lite hence is not available in repeated_field.h.
-DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES_NOINLINE(Message);
+namespace {
+void ShutdownRepeatedFieldAccessor() {
+ internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<int32> >::ShutDown();
+ internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<uint32> >::ShutDown();
+ internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<int64> >::ShutDown();
+ internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<uint64> >::ShutDown();
+ internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<float> >::ShutDown();
+ internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<double> >::ShutDown();
+ internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<bool> >::ShutDown();
+ internal::Singleton<internal::RepeatedPtrFieldStringAccessor>::ShutDown();
+ internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::ShutDown();
+ internal::Singleton<internal::MapFieldAccessor>::ShutDown();
+}
+
+struct ShutdownRepeatedFieldRegister {
+ ShutdownRepeatedFieldRegister() {
+ OnShutdown(&ShutdownRepeatedFieldAccessor);
+ }
+} shutdown_;
+
+} // namespace
+} // namespace internal
+
+namespace internal {
+template<>
+Message* GenericTypeHandler<Message>::NewFromPrototype(
+ const Message* prototype, google::protobuf::Arena* arena) {
+ return prototype->New(arena);
+}
+template<>
+google::protobuf::Arena* GenericTypeHandler<Message>::GetArena(
+ Message* value) {
+ return value->GetArena();
+}
+template<>
+void* GenericTypeHandler<Message>::GetMaybeArenaPointer(
+ Message* value) {
+ return value->GetMaybeArenaPointer();
+}
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index a200bc92..18c092d0 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -98,11 +98,11 @@
//
// // Use the reflection interface to examine the contents.
// const Reflection* reflection = foo->GetReflection();
-// assert(reflection->GetString(foo, text_field) == "Hello World!");
-// assert(reflection->FieldSize(foo, numbers_field) == 3);
-// assert(reflection->GetRepeatedInt32(foo, numbers_field, 0) == 1);
-// assert(reflection->GetRepeatedInt32(foo, numbers_field, 1) == 5);
-// assert(reflection->GetRepeatedInt32(foo, numbers_field, 2) == 42);
+// assert(reflection->GetString(*foo, text_field) == "Hello World!");
+// assert(reflection->FieldSize(*foo, numbers_field) == 3);
+// assert(reflection->GetRepeatedInt32(*foo, numbers_field, 0) == 1);
+// assert(reflection->GetRepeatedInt32(*foo, numbers_field, 1) == 5);
+// assert(reflection->GetRepeatedInt32(*foo, numbers_field, 2) == 42);
//
// delete foo;
// }
@@ -208,7 +208,7 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite {
// This is much, much slower than IsInitialized() as it is implemented
// purely via reflection. Generally, you should not call this unless you
// have already determined that an error exists by calling IsInitialized().
- void FindInitializationErrors(vector<string>* errors) const;
+ void FindInitializationErrors(std::vector<string>* errors) const;
// Like FindInitializationErrors, but joins all the strings, delimited by
// commas, and returns them.
@@ -229,6 +229,11 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite {
// Computes (an estimate of) the total number of bytes currently used for
// storing the message in memory. The default implementation calls the
// Reflection object's SpaceUsed() method.
+ //
+ // SpaceUsed() is noticeably slower than ByteSize(), as it is implemented
+ // using reflection (rather than the generated code implementation for
+ // ByteSize()). Like ByteSize(), its CPU time is linear in the number of
+ // fields defined for the proto.
virtual int SpaceUsed() const;
// Debugging & Testing----------------------------------------------
@@ -456,7 +461,7 @@ class LIBPROTOBUF_EXPORT Reflection {
// Swap fields listed in fields vector of two messages.
virtual void SwapFields(Message* message1,
Message* message2,
- const vector<const FieldDescriptor*>& fields)
+ const std::vector<const FieldDescriptor*>& fields)
const = 0;
// Swap two elements of a repeated field.
@@ -470,8 +475,9 @@ class LIBPROTOBUF_EXPORT Reflection {
// return true and repeated fields will only be listed if FieldSize(field)
// would return non-zero. Fields (both normal fields and extension fields)
// will be listed ordered by field number.
- virtual void ListFields(const Message& message,
- vector<const FieldDescriptor*>* output) const = 0;
+ virtual void ListFields(
+ const Message& message,
+ std::vector<const FieldDescriptor*>* output) const = 0;
// Singular field getters ------------------------------------------
// These get the value of a non-repeated field. They return the default
@@ -523,7 +529,7 @@ class LIBPROTOBUF_EXPORT Reflection {
// regardless of the field's underlying representation. When initializing
// a newly-constructed string, though, it's just as fast and more readable
// to use code like:
- // string str = reflection->GetString(field);
+ // string str = reflection->GetString(message, field);
virtual const string& GetStringReference(const Message& message,
const FieldDescriptor* field,
string* scratch) const = 0;
@@ -842,6 +848,19 @@ class LIBPROTOBUF_EXPORT Reflection {
// }
virtual bool SupportsUnknownEnumValues() const { return false; }
+ // Returns the MessageFactory associated with this message. This can be
+ // useful for determining if a message is a generated message or not, for
+ // example:
+ //
+ // if (message->GetReflection()->GetMessageFactory() ==
+ // google::protobuf::MessageFactory::generated_factory()) {
+ // // This is a generated message.
+ // }
+ //
+ // It can also be used to create more messages of this type, though
+ // Message::New() is an easier way to accomplish this.
+ virtual MessageFactory* GetMessageFactory() const;
+
// ---------------------------------------------------------------------------
protected:
@@ -854,8 +873,6 @@ class LIBPROTOBUF_EXPORT Reflection {
Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
int ctype, const Descriptor* message_type) const = 0;
- virtual MessageFactory* GetMessageFactory() const;
-
// The following methods are used to implement (Mutable)RepeatedFieldRef.
// A Ref object will store a raw pointer to the repeated field data (obtained
// from RepeatedFieldData()) and a pointer to a Accessor (obtained from
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index 63be0e9b..4f63ad2b 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -337,7 +337,7 @@ bool MessageLite::SerializePartialToArray(void* data, int size) const {
string MessageLite::SerializeAsString() const {
// If the compiler implements the (Named) Return Value Optimization,
- // the local variable 'result' will not actually reside on the stack
+ // the local variable 'output' will not actually reside on the stack
// of this function, but will be overlaid with the object that the
// caller supplied for the return value to be constructed in.
string output;
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
index 106982cc..4c16f4c0 100644
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -41,6 +41,7 @@
#include <google/protobuf/stubs/common.h>
+
namespace google {
namespace protobuf {
class Arena;
@@ -133,9 +134,10 @@ class LIBPROTOBUF_EXPORT MessageLite {
// just simple wrappers around MergeFromCodedStream(). Clear() will be called
// before merging the input.
- // Fill the message with a protocol buffer parsed from the given input
- // stream. Returns false on a read error or if the input is in the
- // wrong format.
+ // Fill the message with a protocol buffer parsed from the given input stream.
+ // Returns false on a read error or if the input is in the wrong format. A
+ // successful return does not indicate the entire input is consumed, ensure
+ // you call ConsumedEntireMessage() to check that if applicable.
bool ParseFromCodedStream(io::CodedInputStream* input);
// Like ParseFromCodedStream(), but accepts messages that are missing
// required fields.
@@ -154,7 +156,11 @@ class LIBPROTOBUF_EXPORT MessageLite {
// missing required fields.
bool ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input,
int size);
- // Parse a protocol buffer contained in a string.
+ // Parses a protocol buffer contained in a string. Returns true on success.
+ // This function takes a string in the (non-human-readable) binary wire
+ // format, matching the encoding output by MessageLite::SerializeToString().
+ // If you'd like to convert a human-readable string into a protocol buffer
+ // object, see google::protobuf::TextFormat::ParseFromString().
bool ParseFromString(const string& data);
// Like ParseFromString(), but accepts messages that are missing
// required fields.
@@ -232,6 +238,9 @@ class LIBPROTOBUF_EXPORT MessageLite {
// Computes the serialized size of the message. This recursively calls
// ByteSize() on all embedded messages. If a subclass does not override
// this, it MUST override SetCachedSize().
+ //
+ // ByteSize() is generally linear in the number of fields defined for the
+ // proto.
virtual int ByteSize() const = 0;
// Serializes the message without recomputing the size. The message must
diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc
index ebfb4321..75d60b8b 100644
--- a/src/google/protobuf/message_unittest.cc
+++ b/src/google/protobuf/message_unittest.cc
@@ -45,12 +45,13 @@
#include <sstream>
#include <fstream>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/test_util.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
@@ -205,6 +206,28 @@ TEST(MessageTest, InitializationErrorString) {
EXPECT_EQ("a, b, c", message.InitializationErrorString());
}
+TEST(MessageTest, DynamicCastToGenerated) {
+ unittest::TestAllTypes test_all_types;
+
+ google::protobuf::Message* test_all_types_pointer = &test_all_types;
+ EXPECT_EQ(&test_all_types,
+ google::protobuf::internal::DynamicCastToGenerated<unittest::TestAllTypes>(
+ test_all_types_pointer));
+ EXPECT_EQ(NULL,
+ google::protobuf::internal::DynamicCastToGenerated<unittest::TestRequired>(
+ test_all_types_pointer));
+
+ const google::protobuf::Message* test_all_types_pointer_const = &test_all_types;
+ EXPECT_EQ(
+ &test_all_types,
+ google::protobuf::internal::DynamicCastToGenerated<const unittest::TestAllTypes>(
+ test_all_types_pointer_const));
+ EXPECT_EQ(
+ NULL,
+ google::protobuf::internal::DynamicCastToGenerated<const unittest::TestRequired>(
+ test_all_types_pointer_const));
+}
+
#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet.
TEST(MessageTest, SerializeFailsIfNotInitialized) {
diff --git a/src/google/protobuf/new_delete_capture.cc b/src/google/protobuf/new_delete_capture.cc
deleted file mode 100644
index baf42ffe..00000000
--- a/src/google/protobuf/new_delete_capture.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This file exists for testing allocation behavior when using arenas by hooking
-// new/delete. It is a copy of //experimental/mvels/util/new_delete_capture.cc.
-
-#include <google/protobuf/new_delete_capture.h>
-
-#include <pthread.h>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/malloc_hook.h>
-#include <google/protobuf/stubs/spinlock.h>
-
-namespace google {
-namespace {
-
-pthread_t gthread;
-protobuf_unittest::NewDeleteCapture *ghooked_instance = NULL;
-SpinLock gspinlock(base::LINKER_INITIALIZED);
-
-} // namespace
-
-namespace protobuf_unittest {
-
-NewDeleteCapture::NewDeleteCapture()
- : alloc_count_(0),
- alloc_size_(0),
- alloc_ptr_(NULL),
- free_count_(0),
- free_ptr_(NULL) {}
-
-NewDeleteCapture::~NewDeleteCapture() { Unhook(); }
-
-void NewDeleteCapture::Reset() {
- alloc_count_ = 0;
- alloc_size_ = 0;
- free_count_ = 0;
- alloc_ptr_ = NULL;
- free_ptr_ = NULL;
-}
-
-bool NewDeleteCapture::Hook(bool reset) {
- SpinLockHolder spinlock(&gspinlock);
- if (ghooked_instance != this) {
- GOOGLE_CHECK(ghooked_instance == NULL)
- << " NewDeleteCapture can have only 1 active instance";
- GOOGLE_CHECK(MallocHook::AddNewHook(NewHook));
- GOOGLE_CHECK(MallocHook::AddDeleteHook(DeleteHook));
- gthread = pthread_self();
- ghooked_instance = this;
- if (reset) {
- Reset();
- }
- return true;
- }
- return false;
-}
-
-bool NewDeleteCapture::Unhook() {
- SpinLockHolder spinlock(&gspinlock);
- if (ghooked_instance == this) {
- gthread = pthread_t();
- ghooked_instance = NULL;
- GOOGLE_CHECK(MallocHook::RemoveDeleteHook(DeleteHook));
- GOOGLE_CHECK(MallocHook::RemoveNewHook(NewHook));
- return true;
- }
- return false;
-}
-
-void NewDeleteCapture::NewHook(const void *ptr, size_t size) {
- SpinLockHolder spinlock(&gspinlock);
- if (gthread == pthread_self()) {
- auto &rthis = *ghooked_instance;
- if (++rthis.alloc_count_ == 1) {
- rthis.alloc_size_ = size;
- rthis.alloc_ptr_ = ptr;
- }
- }
-}
-
-void NewDeleteCapture::DeleteHook(const void *ptr) {
- SpinLockHolder spinlock(&gspinlock);
- if (gthread == pthread_self()) {
- auto &rthis = *ghooked_instance;
- if (++rthis.free_count_ == 1) {
- rthis.free_ptr_ = ptr;
- }
- }
-}
-
-} // namespace protobuf_unittest
-} // namespace google
diff --git a/src/google/protobuf/new_delete_capture.h b/src/google/protobuf/new_delete_capture.h
deleted file mode 100644
index 4ab550cd..00000000
--- a/src/google/protobuf/new_delete_capture.h
+++ /dev/null
@@ -1,175 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This file exists for testing allocation behavior when using arenas by hooking
-// new/delete. It is a copy of //experimental/mvels/util/new_delete_capture.h.
-//
-// Copyright 2014 Google Inc.
-//
-// Author: Martijn Vels
-//
-// A simple class that captures memory allocations and deletes.
-//
-// This class is private to //strings and only intended to be used inside
-// unit tests. It uses the MallocHook functionality to capture memory
-// allocation and delete operations performed by the thread that activated
-// a hook on a specific instance.
-//
-// The class captures the following information:
-// - Total allocation count (new, malloc(), etc).
-// - Total delete count (delete, free(), etc).
-// - The size and returned pointer for the first memory allocation.
-// - The pointer for the first delete operation.
-//
-// The latter 2 infos (size and pointer of first new/delete) are usefull in
-// cases where you can closely scope a Hook() / Unhook sequence around a
-// specific piece of code where you expect no more than 1 pair of new / delete
-// operations.
-//
-// Sample usage where we expect a single unique alloc / free:
-//
-// NewDeleteCapture capture_alloc;
-// const void *ptr;
-// {
-// capture_alloc.Hook();
-// MyAllocationClass my_instance(size);
-// capture_alloc.Unhook();
-//
-// ptr = my_instance.ptr();
-// GOOGLE_CHECK_EQ(1, capture_alloc.alloc_count());
-// GOOGLE_CHECK_EQ(0, capture_alloc.free_count());
-// GOOGLE_CHECK_EQ(size, capture_alloc.alloc_size());
-// GOOGLE_CHECK_EQ(ptr, capture_alloc.alloc_ptr());
-//
-// capture_alloc.Hook();
-// }
-// capture_alloc.Unhook();
-// GOOGLE_CHECK_EQ(1, capture_alloc.alloc_count());
-// GOOGLE_CHECK_EQ(1, capture_alloc.free_count());
-// GOOGLE_CHECK_EQ(ptr, capture_alloc.free_ptr());
-//
-// You can only have one NewDeleteCapture instance active at the time. It is
-// total valid to have many instances in different threads, but only one
-// instance can have a hook active.
-//
-// Legal:
-//
-// NewDeleteCapture capture_alloc1;
-// NewDeleteCapture capture_alloc2;
-// const void *ptr;
-// {
-// capture_alloc1.Hook();
-// MyAllocationClass my_instance(size);
-// capture_alloc1.Unhook();
-//
-// capture_alloc2.Hook();
-// my_instance.reset(size);
-// capture_alloc2.Unhook();
-// }
-//
-// Illegal:
-//
-// NewDeleteCapture capture_alloc1;
-// NewDeleteCapture capture_alloc2;
-// const void *ptr;
-// {
-// capture_alloc1.Hook();
-// MyAllocationClass my_instance(size);
-//
-// capture_alloc2.Hook();
-// my_instance.reset(size);
-//
-// capture_alloc1.Unhook();
-// capture_alloc2.Unhook();
-// }
-//
-#ifndef GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__
-#define GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__
-
-#include <stddef.h>
-
-namespace google {
-namespace protobuf_unittest {
-
-class NewDeleteCapture {
- public:
- // Creates a new inactive capture instance
- NewDeleteCapture();
-
- // Destroys this capture instance. Active hooks are automatically removed.
- ~NewDeleteCapture();
-
- // Activates a hook on this instance. If reset is true (the default), all
- // internal counters will be reset to 0.
- // Returns true if the hook was activated, false if this instance already
- // owned the hook.
- // Requires no other instance owning the hook (check fails)
- bool Hook(bool reset = true);
-
- // De-activate the hook on this instance.
- // Returns true if the hook was removed, false if this instance did not own
- // the hook.
- bool Unhook();
-
- // Resets all counters to 0
- void Reset();
-
- // Returns the total number of allocations (new, malloc(), etc)
- size_t alloc_count() const { return alloc_count_; }
-
- // Returns the total number of deletes (delete, free(), etc)
- size_t free_count() const { return free_count_; }
-
- // Returns the size of the first observed allocation
- size_t alloc_size() const { return alloc_size_; }
-
- // Returns the allocated ptr of the first observed allocation
- const void *alloc_ptr() const { return alloc_ptr_; }
-
- // Returns the ptr of the first observed delete
- const void* free_ptr() const { return free_ptr_; }
-
- private:
- static void NewHook(const void *ptr, size_t size);
- static void DeleteHook(const void *ptr);
-
- private:
- size_t alloc_count_;
- size_t alloc_size_;
- const void *alloc_ptr_;
-
- size_t free_count_;
- const void *free_ptr_;
-};
-
-} // namespace protobuf_unittest
-
-} // namespace google
-#endif // GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__
diff --git a/src/google/protobuf/preserve_unknown_enum_test.cc b/src/google/protobuf/preserve_unknown_enum_test.cc
index 816e52ca..1673e8af 100644
--- a/src/google/protobuf/preserve_unknown_enum_test.cc
+++ b/src/google/protobuf/preserve_unknown_enum_test.cc
@@ -30,6 +30,7 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/unittest_preserve_unknown_enum.pb.h>
+#include <google/protobuf/unittest_preserve_unknown_enum2.pb.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/descriptor.h>
#include <gtest/gtest.h>
@@ -39,46 +40,55 @@ namespace protobuf {
namespace {
void FillMessage(
- proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra* message) {
+ proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra* message) {
message->set_e(
- proto2_preserve_unknown_enum_unittest::E_EXTRA);
+ proto3_preserve_unknown_enum_unittest::E_EXTRA);
message->add_repeated_e(
- proto2_preserve_unknown_enum_unittest::E_EXTRA);
+ proto3_preserve_unknown_enum_unittest::E_EXTRA);
message->add_repeated_packed_e(
- proto2_preserve_unknown_enum_unittest::E_EXTRA);
+ proto3_preserve_unknown_enum_unittest::E_EXTRA);
+ message->add_repeated_packed_unexpected_e(
+ proto3_preserve_unknown_enum_unittest::E_EXTRA);
message->set_oneof_e_1(
- proto2_preserve_unknown_enum_unittest::E_EXTRA);
+ proto3_preserve_unknown_enum_unittest::E_EXTRA);
}
void CheckMessage(
- const proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra& message) {
- EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA,
+ const proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra& message) {
+ EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
message.e());
EXPECT_EQ(1, message.repeated_e_size());
- EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA,
+ EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
message.repeated_e(0));
EXPECT_EQ(1, message.repeated_packed_e_size());
- EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA,
+ EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
message.repeated_packed_e(0));
- EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA,
+ EXPECT_EQ(1, message.repeated_packed_unexpected_e_size());
+ EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
+ message.repeated_packed_unexpected_e(0));
+ EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
message.oneof_e_1());
}
void CheckMessage(
- const proto2_preserve_unknown_enum_unittest::MyMessage& message) {
+ const proto3_preserve_unknown_enum_unittest::MyMessage& message) {
EXPECT_EQ(static_cast<int>(
- proto2_preserve_unknown_enum_unittest::E_EXTRA),
+ proto3_preserve_unknown_enum_unittest::E_EXTRA),
static_cast<int>(message.e()));
EXPECT_EQ(1, message.repeated_e_size());
EXPECT_EQ(static_cast<int>(
- proto2_preserve_unknown_enum_unittest::E_EXTRA),
+ proto3_preserve_unknown_enum_unittest::E_EXTRA),
static_cast<int>(message.repeated_e(0)));
EXPECT_EQ(1, message.repeated_packed_e_size());
EXPECT_EQ(static_cast<int>(
- proto2_preserve_unknown_enum_unittest::E_EXTRA),
+ proto3_preserve_unknown_enum_unittest::E_EXTRA),
static_cast<int>(message.repeated_packed_e(0)));
+ EXPECT_EQ(1, message.repeated_packed_unexpected_e_size());
EXPECT_EQ(static_cast<int>(
- proto2_preserve_unknown_enum_unittest::E_EXTRA),
+ proto3_preserve_unknown_enum_unittest::E_EXTRA),
+ static_cast<int>(message.repeated_packed_unexpected_e(0)));
+ EXPECT_EQ(static_cast<int>(
+ proto3_preserve_unknown_enum_unittest::E_EXTRA),
static_cast<int>(message.oneof_e_1()));
}
@@ -87,12 +97,12 @@ void CheckMessage(
// Test that parsing preserves an unknown value in the enum field and does not
// punt it to the UnknownFieldSet.
TEST(PreserveUnknownEnumTest, PreserveParseAndSerialize) {
- proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+ proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
FillMessage(&orig_message);
string serialized;
orig_message.SerializeToString(&serialized);
- proto2_preserve_unknown_enum_unittest::MyMessage message;
+ proto3_preserve_unknown_enum_unittest::MyMessage message;
EXPECT_EQ(true, message.ParseFromString(serialized));
CheckMessage(message);
@@ -105,13 +115,13 @@ TEST(PreserveUnknownEnumTest, PreserveParseAndSerialize) {
// Test that reflection based implementation also keeps unknown enum values and
// doesn't put them into UnknownFieldSet.
TEST(PreserveUnknownEnumTest, PreserveParseAndSerializeDynamicMessage) {
- proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+ proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
FillMessage(&orig_message);
string serialized = orig_message.SerializeAsString();
google::protobuf::DynamicMessageFactory factory;
google::protobuf::scoped_ptr<google::protobuf::Message> message(factory.GetPrototype(
- proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New());
+ proto3_preserve_unknown_enum_unittest::MyMessage::descriptor())->New());
EXPECT_EQ(true, message->ParseFromString(serialized));
message->DiscardUnknownFields();
@@ -120,14 +130,61 @@ TEST(PreserveUnknownEnumTest, PreserveParseAndSerializeDynamicMessage) {
CheckMessage(orig_message);
}
+// Test that for proto2 messages, unknown values are in unknown fields.
+TEST(PreserveUnknownEnumTest, Proto2HidesUnknownValues) {
+ proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+ FillMessage(&orig_message);
+
+ string serialized;
+ orig_message.SerializeToString(&serialized);
+
+ proto2_preserve_unknown_enum_unittest::MyMessage message;
+ EXPECT_EQ(true, message.ParseFromString(serialized));
+ // The intermediate message has everything in its "unknown fields".
+ proto2_preserve_unknown_enum_unittest::MyMessage message2 = message;
+ message2.DiscardUnknownFields();
+ EXPECT_EQ(0, message2.ByteSize());
+
+ // But when we pass it to the correct structure, all values are there.
+ serialized.clear();
+ message.SerializeToString(&serialized);
+ EXPECT_EQ(true, orig_message.ParseFromString(serialized));
+ CheckMessage(orig_message);
+}
+
+// Same as before, for a dynamic message.
+TEST(PreserveUnknownEnumTest, DynamicProto2HidesUnknownValues) {
+ proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+ FillMessage(&orig_message);
+
+ string serialized;
+ orig_message.SerializeToString(&serialized);
+
+ google::protobuf::DynamicMessageFactory factory;
+ google::protobuf::scoped_ptr<google::protobuf::Message> message(factory.GetPrototype(
+ proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New());
+ EXPECT_EQ(true, message->ParseFromString(serialized));
+ // The intermediate message has everything in its "unknown fields".
+ proto2_preserve_unknown_enum_unittest::MyMessage message2;
+ message2.CopyFrom(*message);
+ message2.DiscardUnknownFields();
+ EXPECT_EQ(0, message2.ByteSize());
+
+ // But when we pass it to the correct structure, all values are there.
+ serialized.clear();
+ message->SerializeToString(&serialized);
+ EXPECT_EQ(true, orig_message.ParseFromString(serialized));
+ CheckMessage(orig_message);
+}
+
// Test that reflection provides EnumValueDescriptors for unknown values.
TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) {
- proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+ proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
FillMessage(&orig_message);
string serialized;
orig_message.SerializeToString(&serialized);
- proto2_preserve_unknown_enum_unittest::MyMessage message;
+ proto3_preserve_unknown_enum_unittest::MyMessage message;
EXPECT_EQ(true, message.ParseFromString(serialized));
CheckMessage(message);
@@ -138,7 +195,7 @@ TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) {
// This should dynamically create an EnumValueDescriptor.
const google::protobuf::EnumValueDescriptor* enum_value = r->GetEnum(message, field);
EXPECT_EQ(enum_value->number(),
- static_cast<int>(proto2_preserve_unknown_enum_unittest::E_EXTRA));
+ static_cast<int>(proto3_preserve_unknown_enum_unittest::E_EXTRA));
// Fetching value for a second time should return the same pointer.
const google::protobuf::EnumValueDescriptor* enum_value_second =
@@ -150,7 +207,7 @@ TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) {
d->FindFieldByName("repeated_e");
enum_value = r->GetRepeatedEnum(message, repeated_field, 0);
EXPECT_EQ(enum_value->number(),
- static_cast<int>(proto2_preserve_unknown_enum_unittest::E_EXTRA));
+ static_cast<int>(proto3_preserve_unknown_enum_unittest::E_EXTRA));
// Should reuse the same EnumValueDescriptor, even for a different field.
EXPECT_EQ(enum_value, enum_value_second);
@@ -164,7 +221,7 @@ TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) {
// Test that the new integer-based enum reflection API works.
TEST(PreserveUnknownEnumTest, IntegerEnumReflectionAPI) {
- proto2_preserve_unknown_enum_unittest::MyMessage message;
+ proto3_preserve_unknown_enum_unittest::MyMessage message;
const google::protobuf::Reflection* r = message.GetReflection();
const google::protobuf::Descriptor* d = message.GetDescriptor();
@@ -189,8 +246,6 @@ TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) {
protobuf_unittest::TestAllTypes message; // proto2 message
const google::protobuf::Reflection* r = message.GetReflection();
const google::protobuf::Descriptor* d = message.GetDescriptor();
- const google::protobuf::FieldDescriptor* singular_field =
- d->FindFieldByName("optional_nested_enum");
const google::protobuf::FieldDescriptor* repeated_field =
d->FindFieldByName("repeated_nested_enum");
// Add one element to the repeated field so that we can test
@@ -201,6 +256,8 @@ TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) {
r->AddEnum(&message, repeated_field, enum_value);
#ifdef PROTOBUF_HAS_DEATH_TEST
+ const google::protobuf::FieldDescriptor* singular_field =
+ d->FindFieldByName("optional_nested_enum");
// Enum-field integer-based setters GOOGLE_DCHECK-fail on invalid values, in order to
// remain consistent with proto2 generated code.
EXPECT_DEBUG_DEATH({
@@ -220,7 +277,7 @@ TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) {
TEST(PreserveUnknownEnumTest, SupportsUnknownEnumValuesAPI) {
protobuf_unittest::TestAllTypes proto2_message;
- proto2_preserve_unknown_enum_unittest::MyMessage new_message;
+ proto3_preserve_unknown_enum_unittest::MyMessage new_message;
const google::protobuf::Reflection* proto2_reflection = proto2_message.GetReflection();
const google::protobuf::Reflection* new_reflection = new_message.GetReflection();
diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc
index c3b5996f..da4be673 100644
--- a/src/google/protobuf/proto3_arena_unittest.cc
+++ b/src/google/protobuf/proto3_arena_unittest.cc
@@ -180,6 +180,16 @@ TEST(ArenaTest, ReleaseMessage) {
EXPECT_EQ(118, nested->bb());
}
+TEST(ArenaTest, MessageFieldClear) {
+ // GitHub issue #310: https://github.com/google/protobuf/issues/310
+ Arena arena;
+ TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ arena_message->mutable_optional_nested_message()->set_bb(118);
+ // This should not crash, but prior to the bugfix, it tried to use `operator
+ // delete` the nested message (which is on the arena):
+ arena_message->Clear();
+}
+
} // namespace
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/reflection.h b/src/google/protobuf/reflection.h
index 17d89a18..4ff0f6b4 100644..100755
--- a/src/google/protobuf/reflection.h
+++ b/src/google/protobuf/reflection.h
@@ -33,7 +33,13 @@
#ifndef GOOGLE_PROTOBUF_REFLECTION_H__
#define GOOGLE_PROTOBUF_REFLECTION_H__
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
#include <google/protobuf/message.h>
+#include <google/protobuf/generated_enum_util.h>
namespace google {
namespace protobuf {
@@ -223,7 +229,7 @@ class RepeatedFieldRef<
const Message* default_instance_;
};
-// MutableRepeatedFieldRef definition for non-message types.
+// MutableRepeatedFieldRef definition for message types.
template<typename T>
class MutableRepeatedFieldRef<
T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
@@ -297,10 +303,298 @@ class MutableRepeatedFieldRef<
const AccessorType* accessor_;
const Message* default_instance_;
};
+
+namespace internal {
+// Interfaces used to implement reflection RepeatedFieldRef API.
+// Reflection::GetRepeatedAccessor() should return a pointer to an singleton
+// object that implements the below interface.
+//
+// This interface passes/returns values using void pointers. The actual type
+// of the value depends on the field's cpp_type. Following is a mapping from
+// cpp_type to the type that should be used in this interface:
+//
+// field->cpp_type() T Actual type of void*
+// CPPTYPE_INT32 int32 int32
+// CPPTYPE_UINT32 uint32 uint32
+// CPPTYPE_INT64 int64 int64
+// CPPTYPE_UINT64 uint64 uint64
+// CPPTYPE_DOUBLE double double
+// CPPTYPE_FLOAT float float
+// CPPTYPE_BOOL bool bool
+// CPPTYPE_ENUM generated enum type int32
+// CPPTYPE_STRING string string
+// CPPTYPE_MESSAGE generated message type google::protobuf::Message
+// or google::protobuf::Message
+//
+// Note that for enums we use int32 in the interface.
+//
+// You can map from T to the actual type using RefTypeTraits:
+// typedef RefTypeTraits<T>::AccessorValueType ActualType;
+class LIBPROTOBUF_EXPORT RepeatedFieldAccessor {
+ public:
+ // Typedefs for clarity.
+ typedef void Field;
+ typedef void Value;
+ typedef void Iterator;
+
+ virtual ~RepeatedFieldAccessor();
+ virtual bool IsEmpty(const Field* data) const = 0;
+ virtual int Size(const Field* data) const = 0;
+ // Depends on the underlying representation of the repeated field, this
+ // method can return a pointer to the underlying object if such an object
+ // exists, or fill the data into scratch_space and return scratch_space.
+ // Callers of this method must ensure scratch_space is a valid pointer
+ // to a mutable object of the correct type.
+ virtual const Value* Get(
+ const Field* data, int index, Value* scratch_space) const = 0;
+
+ virtual void Clear(Field* data) const = 0;
+ virtual void Set(Field* data, int index, const Value* value) const = 0;
+ virtual void Add(Field* data, const Value* value) const = 0;
+ virtual void RemoveLast(Field* data) const = 0;
+ virtual void SwapElements(Field* data, int index1, int index2) const = 0;
+ virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator,
+ Field* other_data) const = 0;
+
+ // Create an iterator that points at the begining of the repeated field.
+ virtual Iterator* BeginIterator(const Field* data) const = 0;
+ // Create an iterator that points at the end of the repeated field.
+ virtual Iterator* EndIterator(const Field* data) const = 0;
+ // Make a copy of an iterator and return the new copy.
+ virtual Iterator* CopyIterator(const Field* data,
+ const Iterator* iterator) const = 0;
+ // Move an iterator to point to the next element.
+ virtual Iterator* AdvanceIterator(const Field* data,
+ Iterator* iterator) const = 0;
+ // Compare whether two iterators point to the same element.
+ virtual bool EqualsIterator(const Field* data, const Iterator* a,
+ const Iterator* b) const = 0;
+ // Delete an iterator created by BeginIterator(), EndIterator() and
+ // CopyIterator().
+ virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0;
+ // Like Get() but for iterators.
+ virtual const Value* GetIteratorValue(const Field* data,
+ const Iterator* iterator,
+ Value* scratch_space) const = 0;
+
+ // Templated methods that make using this interface easier for non-message
+ // types.
+ template<typename T>
+ T Get(const Field* data, int index) const {
+ typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+ ActualType scratch_space;
+ return static_cast<T>(
+ *reinterpret_cast<const ActualType*>(
+ Get(data, index, static_cast<Value*>(&scratch_space))));
+ }
+
+ template<typename T, typename ValueType>
+ void Set(Field* data, int index, const ValueType& value) const {
+ typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+ // In this RepeatedFieldAccessor interface we pass/return data using
+ // raw pointers. Type of the data these raw pointers point to should
+ // be ActualType. Here we have a ValueType object and want a ActualType
+ // pointer. We can't cast a ValueType pointer to an ActualType pointer
+ // directly because their type might be different (for enums ValueType
+ // may be a generated enum type while ActualType is int32). To be safe
+ // we make a copy to get a temporary ActualType object and use it.
+ ActualType tmp = static_cast<ActualType>(value);
+ Set(data, index, static_cast<const Value*>(&tmp));
+ }
+
+ template<typename T, typename ValueType>
+ void Add(Field* data, const ValueType& value) const {
+ typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+ // In this RepeatedFieldAccessor interface we pass/return data using
+ // raw pointers. Type of the data these raw pointers point to should
+ // be ActualType. Here we have a ValueType object and want a ActualType
+ // pointer. We can't cast a ValueType pointer to an ActualType pointer
+ // directly because their type might be different (for enums ValueType
+ // may be a generated enum type while ActualType is int32). To be safe
+ // we make a copy to get a temporary ActualType object and use it.
+ ActualType tmp = static_cast<ActualType>(value);
+ Add(data, static_cast<const Value*>(&tmp));
+ }
+};
+
+// Implement (Mutable)RepeatedFieldRef::iterator
+template<typename T>
+class RepeatedFieldRefIterator
+ : public std::iterator<std::forward_iterator_tag, T> {
+ typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
+ typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
+ typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;
+
+ public:
+ // Constructor for non-message fields.
+ RepeatedFieldRefIterator(const void* data,
+ const RepeatedFieldAccessor* accessor,
+ bool begin)
+ : data_(data), accessor_(accessor),
+ iterator_(begin ? accessor->BeginIterator(data) :
+ accessor->EndIterator(data)),
+ scratch_space_(new AccessorValueType) {
+ }
+ // Constructor for message fields.
+ RepeatedFieldRefIterator(const void* data,
+ const RepeatedFieldAccessor* accessor,
+ bool begin,
+ AccessorValueType* scratch_space)
+ : data_(data), accessor_(accessor),
+ iterator_(begin ? accessor->BeginIterator(data) :
+ accessor->EndIterator(data)),
+ scratch_space_(scratch_space) {
+ }
+ ~RepeatedFieldRefIterator() {
+ accessor_->DeleteIterator(data_, iterator_);
+ }
+ RepeatedFieldRefIterator operator++(int) {
+ RepeatedFieldRefIterator tmp(*this);
+ iterator_ = accessor_->AdvanceIterator(data_, iterator_);
+ return tmp;
+ }
+ RepeatedFieldRefIterator& operator++() {
+ iterator_ = accessor_->AdvanceIterator(data_, iterator_);
+ return *this;
+ }
+ IteratorValueType operator*() const {
+ return static_cast<IteratorValueType>(
+ *static_cast<const AccessorValueType*>(
+ accessor_->GetIteratorValue(
+ data_, iterator_, scratch_space_.get())));
+ }
+ IteratorPointerType operator->() const {
+ return static_cast<IteratorPointerType>(
+ accessor_->GetIteratorValue(
+ data_, iterator_, scratch_space_.get()));
+ }
+ bool operator!=(const RepeatedFieldRefIterator& other) const {
+ assert(data_ == other.data_);
+ assert(accessor_ == other.accessor_);
+ return !accessor_->EqualsIterator(data_, iterator_, other.iterator_);
+ }
+ bool operator==(const RepeatedFieldRefIterator& other) const {
+ return !this->operator!=(other);
+ }
+
+ RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other)
+ : data_(other.data_), accessor_(other.accessor_),
+ iterator_(accessor_->CopyIterator(data_, other.iterator_)) {
+ }
+ RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) {
+ if (this != &other) {
+ accessor_->DeleteIterator(data_, iterator_);
+ data_ = other.data_;
+ accessor_ = other.accessor_;
+ iterator_ = accessor_->CopyIterator(data_, other.iterator_);
+ }
+ return *this;
+ }
+
+ protected:
+ const void* data_;
+ const RepeatedFieldAccessor* accessor_;
+ void* iterator_;
+ google::protobuf::scoped_ptr<AccessorValueType> scratch_space_;
+};
+
+// TypeTraits that maps the type parameter T of RepeatedFieldRef or
+// MutableRepeatedFieldRef to corresponding iterator type,
+// RepeatedFieldAccessor type, etc.
+template<typename T>
+struct PrimitiveTraits {
+ static const bool is_primitive = false;
+};
+#define DEFINE_PRIMITIVE(TYPE, type) \
+ template<> struct PrimitiveTraits<type> { \
+ static const bool is_primitive = true; \
+ static const FieldDescriptor::CppType cpp_type = \
+ FieldDescriptor::CPPTYPE_ ## TYPE; \
+ };
+DEFINE_PRIMITIVE(INT32, int32)
+DEFINE_PRIMITIVE(UINT32, uint32)
+DEFINE_PRIMITIVE(INT64, int64)
+DEFINE_PRIMITIVE(UINT64, uint64)
+DEFINE_PRIMITIVE(FLOAT, float)
+DEFINE_PRIMITIVE(DOUBLE, double)
+DEFINE_PRIMITIVE(BOOL, bool)
+#undef DEFINE_PRIMITIVE
+
+template<typename T>
+struct RefTypeTraits<
+ T, typename internal::enable_if<PrimitiveTraits<T>::is_primitive>::type> {
+ typedef RepeatedFieldRefIterator<T> iterator;
+ typedef RepeatedFieldAccessor AccessorType;
+ typedef T AccessorValueType;
+ typedef T IteratorValueType;
+ typedef T* IteratorPointerType;
+ static const FieldDescriptor::CppType cpp_type =
+ PrimitiveTraits<T>::cpp_type;
+ static const Descriptor* GetMessageFieldDescriptor() {
+ return NULL;
+ }
+};
+
+template<typename T>
+struct RefTypeTraits<
+ T, typename internal::enable_if<is_proto_enum<T>::value>::type> {
+ typedef RepeatedFieldRefIterator<T> iterator;
+ typedef RepeatedFieldAccessor AccessorType;
+ // We use int32 for repeated enums in RepeatedFieldAccessor.
+ typedef int32 AccessorValueType;
+ typedef T IteratorValueType;
+ typedef int32* IteratorPointerType;
+ static const FieldDescriptor::CppType cpp_type =
+ FieldDescriptor::CPPTYPE_ENUM;
+ static const Descriptor* GetMessageFieldDescriptor() {
+ return NULL;
+ }
+};
+
+template<typename T>
+struct RefTypeTraits<
+ T, typename internal::enable_if<internal::is_same<string, T>::value>::type> {
+ typedef RepeatedFieldRefIterator<T> iterator;
+ typedef RepeatedFieldAccessor AccessorType;
+ typedef string AccessorValueType;
+ typedef string IteratorValueType;
+ typedef string* IteratorPointerType;
+ static const FieldDescriptor::CppType cpp_type =
+ FieldDescriptor::CPPTYPE_STRING;
+ static const Descriptor* GetMessageFieldDescriptor() {
+ return NULL;
+ }
+};
+
+template<typename T>
+struct MessageDescriptorGetter {
+ static const Descriptor* get() {
+ return T::default_instance().GetDescriptor();
+ }
+};
+template<>
+struct MessageDescriptorGetter<Message> {
+ static const Descriptor* get() {
+ return NULL;
+ }
+};
+
+template<typename T>
+struct RefTypeTraits<
+ T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
+ typedef RepeatedFieldRefIterator<T> iterator;
+ typedef RepeatedFieldAccessor AccessorType;
+ typedef Message AccessorValueType;
+ typedef const T& IteratorValueType;
+ typedef const T* IteratorPointerType;
+ static const FieldDescriptor::CppType cpp_type =
+ FieldDescriptor::CPPTYPE_MESSAGE;
+ static const Descriptor* GetMessageFieldDescriptor() {
+ return MessageDescriptorGetter<T>::get();
+ }
+};
+} // namespace internal
} // namespace protobuf
} // namespace google
-// Implementation details for (Mutable)RepeatedFieldRef.
-#include <google/protobuf/repeated_field_reflection.h>
-
#endif // GOOGLE_PROTOBUF_REFLECTION_H__
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 4798eeda..14f46298 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -576,26 +576,21 @@ class GenericTypeHandler {
}
};
-// Macros for specializing GenericTypeHandler for base proto types, these are
-// are defined here, to allow inlining them at their callsites.
-#define DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(Inline, TypeName) \
- template<> \
- Inline TypeName* GenericTypeHandler<TypeName>::NewFromPrototype( \
- const TypeName* prototype, google::protobuf::Arena* arena) { \
- return prototype->New(arena); \
- } \
- template<> \
- Inline google::protobuf::Arena* GenericTypeHandler<TypeName>::GetArena( \
- TypeName* value) { \
- return value->GetArena(); \
- } \
- template<> \
- Inline void* GenericTypeHandler<TypeName>::GetMaybeArenaPointer( \
- TypeName* value) { \
- return value->GetMaybeArenaPointer(); \
- }
-#define DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES_NOINLINE(TypeName) \
- DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(, TypeName)
+template<>
+inline MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
+ const MessageLite* prototype, google::protobuf::Arena* arena) {
+ return prototype->New(arena);
+}
+template<>
+inline google::protobuf::Arena* GenericTypeHandler<MessageLite>::GetArena(
+ MessageLite* value) {
+ return value->GetArena();
+}
+template<>
+inline void* GenericTypeHandler<MessageLite>::GetMaybeArenaPointer(
+ MessageLite* value) {
+ return value->GetMaybeArenaPointer();
+}
// Implements GenericTypeHandler specialization required by RepeatedPtrFields
// to work with MessageLite type.
@@ -605,8 +600,6 @@ inline void GenericTypeHandler<MessageLite>::Merge(
to->CheckTypeAndMergeFrom(from);
}
-DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(inline, MessageLite);
-
// Declarations of the specialization as we cannot define them here, as the
// header that defines ProtocolMessage depends on types defined in this header.
#define DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(TypeName) \
@@ -626,7 +619,7 @@ DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(inline, MessageLite);
DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(Message);
-#undef DECLARE_SPECIALIZATIONS_FOR_BASE_CLASSES
+#undef DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES
template <>
inline const MessageLite& GenericTypeHandler<MessageLite>::default_instance() {
@@ -1132,7 +1125,9 @@ template <typename Element>
inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase(
const_iterator first, const_iterator last) {
size_type first_offset = first - cbegin();
- Truncate(std::copy(last, cend(), begin() + first_offset) - cbegin());
+ if (first != last) {
+ Truncate(std::copy(last, cend(), begin() + first_offset) - cbegin());
+ }
return begin() + first_offset;
}
@@ -1235,6 +1230,7 @@ void RepeatedField<Element>::Reserve(int new_size) {
kRepHeaderSize + sizeof(Element)*new_size));
}
rep_->arena = arena;
+ int old_total_size = total_size_;
total_size_ = new_size;
// Invoke placement-new on newly allocated elements. We shouldn't have to do
// this, since Element is supposed to be POD, but a previous version of this
@@ -1253,15 +1249,17 @@ void RepeatedField<Element>::Reserve(int new_size) {
if (current_size_ > 0) {
MoveArray(rep_->elements, old_rep->elements, current_size_);
}
- // 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[current_size_];
- for (; e < limit; e++) {
- e->Element::~Element();
- }
- if (arena == NULL) {
- delete[] reinterpret_cast<char*>(old_rep);
+ 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);
+ }
}
}
@@ -1418,7 +1416,7 @@ void RepeatedPtrFieldBase::Clear() {
const int n = current_size_;
GOOGLE_DCHECK_GE(n, 0);
if (n > 0) {
- void* const* elements = raw_data();
+ void* const* elements = rep_->elements;
int i = 0;
do {
TypeHandler::Clear(cast<TypeHandler>(elements[i++]));
@@ -2264,7 +2262,7 @@ RepeatedPtrField<Element>::pointer_end() const {
// Iterators and helper functions that follow the spirit of the STL
// std::back_insert_iterator and std::back_inserter but are tailor-made
-// for RepeatedField and RepatedPtrField. Typical usage would be:
+// for RepeatedField and RepeatedPtrField. Typical usage would be:
//
// std::copy(some_sequence.begin(), some_sequence.end(),
// google::protobuf::RepeatedFieldBackInserter(proto.mutable_sequence()));
diff --git a/src/google/protobuf/repeated_field_reflection_unittest.cc b/src/google/protobuf/repeated_field_reflection_unittest.cc
index 8b821806..fcebe5ce 100644
--- a/src/google/protobuf/repeated_field_reflection_unittest.cc
+++ b/src/google/protobuf/repeated_field_reflection_unittest.cc
@@ -410,6 +410,7 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) {
EXPECT_TRUE(mrf_message.empty());
#ifdef PROTOBUF_HAS_DEATH_TEST
+
// Make sure types are checked correctly at runtime.
const FieldDescriptor* fd_optional_int32 =
desc->FindFieldByName("optional_int32");
@@ -419,6 +420,7 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) {
message, fd_repeated_int32), "");
EXPECT_DEATH(refl->GetRepeatedFieldRef<TestAllTypes>(
message, fd_repeated_foreign_message), "");
+
#endif // PROTOBUF_HAS_DEATH_TEST
}
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index 15c0c93e..af397932 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -456,6 +456,28 @@ TEST(RepeatedField, ExtractSubrange) {
}
}
+TEST(RepeatedField, ClearThenReserveMore) {
+ // Test that Reserve properly destroys the old internal array when it's forced
+ // to allocate a new one, even when cleared-but-not-deleted objects are
+ // present. Use a 'string' and > 16 bytes length so that the elements are
+ // non-POD and allocate -- the leak checker will catch any skipped destructor
+ // calls here.
+ RepeatedField<string> field;
+ for (int i = 0; i < 32; i++) {
+ field.Add(string("abcdefghijklmnopqrstuvwxyz0123456789"));
+ }
+ EXPECT_EQ(32, field.size());
+ field.Clear();
+ EXPECT_EQ(0, field.size());
+ EXPECT_EQ(32, field.Capacity());
+
+ field.Reserve(1024);
+ EXPECT_EQ(0, field.size());
+ EXPECT_EQ(1024, field.Capacity());
+ // Finish test -- |field| should destroy the cleared-but-not-yet-destroyed
+ // strings.
+}
+
// ===================================================================
// RepeatedPtrField tests. These pretty much just mirror the RepeatedField
// tests above.
@@ -1131,7 +1153,7 @@ TEST_F(RepeatedPtrFieldIteratorTest, STLAlgorithms_lower_bound) {
string v = "f";
RepeatedPtrField<string>::const_iterator it =
- lower_bound(proto_array_.begin(), proto_array_.end(), v);
+ std::lower_bound(proto_array_.begin(), proto_array_.end(), v);
EXPECT_EQ(*it, "n");
EXPECT_TRUE(it == proto_array_.begin() + 3);
@@ -1292,8 +1314,8 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) {
{
string v = "f";
RepeatedPtrField<string>::pointer_iterator it =
- lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(),
- &v, StringLessThan());
+ std::lower_bound(proto_array_.pointer_begin(),
+ proto_array_.pointer_end(), &v, StringLessThan());
GOOGLE_CHECK(*it != NULL);
@@ -1302,10 +1324,9 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) {
}
{
string v = "f";
- RepeatedPtrField<string>::const_pointer_iterator it =
- lower_bound(const_proto_array_->pointer_begin(),
- const_proto_array_->pointer_end(),
- &v, StringLessThan());
+ RepeatedPtrField<string>::const_pointer_iterator it = std::lower_bound(
+ const_proto_array_->pointer_begin(), const_proto_array_->pointer_end(),
+ &v, StringLessThan());
GOOGLE_CHECK(*it != NULL);
@@ -1343,9 +1364,8 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, Sort) {
EXPECT_EQ("foo", proto_array_.Get(0));
EXPECT_EQ("n", proto_array_.Get(5));
EXPECT_EQ("x", proto_array_.Get(9));
- sort(proto_array_.pointer_begin(),
- proto_array_.pointer_end(),
- StringLessThan());
+ std::sort(proto_array_.pointer_begin(), proto_array_.pointer_end(),
+ StringLessThan());
EXPECT_EQ("a", proto_array_.Get(0));
EXPECT_EQ("baz", proto_array_.Get(2));
EXPECT_EQ("y", proto_array_.Get(9));
@@ -1478,9 +1498,9 @@ TEST_F(RepeatedFieldInsertionIteratorsTest,
new_data->set_bb(i);
}
TestAllTypes testproto;
- copy(data.begin(), data.end(),
- AllocatedRepeatedPtrFieldBackInserter(
- testproto.mutable_repeated_nested_message()));
+ std::copy(data.begin(), data.end(),
+ AllocatedRepeatedPtrFieldBackInserter(
+ testproto.mutable_repeated_nested_message()));
EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
}
@@ -1497,9 +1517,8 @@ TEST_F(RepeatedFieldInsertionIteratorsTest,
*new_data = "name-" + SimpleItoa(i);
}
TestAllTypes testproto;
- copy(data.begin(), data.end(),
- AllocatedRepeatedPtrFieldBackInserter(
- testproto.mutable_repeated_string()));
+ std::copy(data.begin(), data.end(), AllocatedRepeatedPtrFieldBackInserter(
+ testproto.mutable_repeated_string()));
EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
}
diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc
new file mode 100644
index 00000000..5c88363f
--- /dev/null
+++ b/src/google/protobuf/source_context.pb.cc
@@ -0,0 +1,387 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/source_context.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "google/protobuf/source_context.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* SourceContext_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ SourceContext_reflection_ = NULL;
+
+} // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fsource_5fcontext_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+ const ::google::protobuf::FileDescriptor* file =
+ ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+ "google/protobuf/source_context.proto");
+ GOOGLE_CHECK(file != NULL);
+ SourceContext_descriptor_ = file->message_type(0);
+ static const int SourceContext_offsets_[1] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceContext, file_name_),
+ };
+ SourceContext_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ SourceContext_descriptor_,
+ SourceContext::default_instance_,
+ SourceContext_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(SourceContext),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceContext, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceContext, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+ ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+ &protobuf_AssignDesc_google_2fprotobuf_2fsource_5fcontext_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ SourceContext_descriptor_, &SourceContext::default_instance());
+}
+
+} // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fsource_5fcontext_2eproto() {
+ delete SourceContext::default_instance_;
+ delete SourceContext_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto() {
+ static bool already_here = false;
+ if (already_here) return;
+ already_here = true;
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+ "\n$google/protobuf/source_context.proto\022\017"
+ "google.protobuf\"\"\n\rSourceContext\022\021\n\tfile"
+ "_name\030\001 \001(\tBR\n\023com.google.protobufB\022Sour"
+ "ceContextProtoP\001\242\002\003GPB\252\002\036Google.Protobuf"
+ ".WellKnownTypesb\006proto3", 183);
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+ "google/protobuf/source_context.proto", &protobuf_RegisterTypes);
+ SourceContext::default_instance_ = new SourceContext();
+ SourceContext::default_instance_->InitAsDefaultInstance();
+ ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fsource_5fcontext_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fsource_5fcontext_2eproto {
+ StaticDescriptorInitializer_google_2fprotobuf_2fsource_5fcontext_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+ }
+} static_descriptor_initializer_google_2fprotobuf_2fsource_5fcontext_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+ GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+} // namespace
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int SourceContext::kFileNameFieldNumber;
+#endif // !_MSC_VER
+
+SourceContext::SourceContext()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.SourceContext)
+}
+
+void SourceContext::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+SourceContext::SourceContext(const SourceContext& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceContext)
+}
+
+void SourceContext::SharedCtor() {
+ _is_default_instance_ = false;
+ ::google::protobuf::internal::GetEmptyString();
+ _cached_size_ = 0;
+ file_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+SourceContext::~SourceContext() {
+ // @@protoc_insertion_point(destructor:google.protobuf.SourceContext)
+ SharedDtor();
+}
+
+void SourceContext::SharedDtor() {
+ file_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (this != default_instance_) {
+ }
+}
+
+void SourceContext::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* SourceContext::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return SourceContext_descriptor_;
+}
+
+const SourceContext& SourceContext::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+ return *default_instance_;
+}
+
+SourceContext* SourceContext::default_instance_ = NULL;
+
+SourceContext* SourceContext::New(::google::protobuf::Arena* arena) const {
+ SourceContext* n = new SourceContext;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void SourceContext::Clear() {
+ file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+bool SourceContext::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.SourceContext)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional string file_name = 1;
+ case 1: {
+ if (tag == 10) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_file_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->file_name().data(), this->file_name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.SourceContext.file_name");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.SourceContext)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.SourceContext)
+ return false;
+#undef DO_
+}
+
+void SourceContext::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.SourceContext)
+ // optional string file_name = 1;
+ if (this->file_name().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->file_name().data(), this->file_name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.SourceContext.file_name");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 1, this->file_name(), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.SourceContext)
+}
+
+::google::protobuf::uint8* SourceContext::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceContext)
+ // optional string file_name = 1;
+ if (this->file_name().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->file_name().data(), this->file_name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.SourceContext.file_name");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 1, this->file_name(), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceContext)
+ return target;
+}
+
+int SourceContext::ByteSize() const {
+ int total_size = 0;
+
+ // optional string file_name = 1;
+ if (this->file_name().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->file_name());
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void SourceContext::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const SourceContext* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const SourceContext>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void SourceContext::MergeFrom(const SourceContext& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from.file_name().size() > 0) {
+
+ file_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.file_name_);
+ }
+}
+
+void SourceContext::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void SourceContext::CopyFrom(const SourceContext& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool SourceContext::IsInitialized() const {
+
+ return true;
+}
+
+void SourceContext::Swap(SourceContext* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void SourceContext::InternalSwap(SourceContext* other) {
+ file_name_.Swap(&other->file_name_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata SourceContext::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = SourceContext_descriptor_;
+ metadata.reflection = SourceContext_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// SourceContext
+
+// optional string file_name = 1;
+void SourceContext::clear_file_name() {
+ file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& SourceContext::file_name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.SourceContext.file_name)
+ return file_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceContext::set_file_name(const ::std::string& value) {
+
+ file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.SourceContext.file_name)
+}
+ void SourceContext::set_file_name(const char* value) {
+
+ file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.SourceContext.file_name)
+}
+ void SourceContext::set_file_name(const char* value, size_t size) {
+
+ file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceContext.file_name)
+}
+ ::std::string* SourceContext::mutable_file_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.SourceContext.file_name)
+ return file_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* SourceContext::release_file_name() {
+
+ return file_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceContext::set_allocated_file_name(::std::string* file_name) {
+ if (file_name != NULL) {
+
+ } else {
+
+ }
+ file_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), file_name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceContext.file_name)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h
new file mode 100644
index 00000000..02e11460
--- /dev/null
+++ b/src/google/protobuf/source_context.pb.h
@@ -0,0 +1,185 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/source_context.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fsource_5fcontext_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fsource_5fcontext_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fsource_5fcontext_2eproto();
+
+class SourceContext;
+
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT SourceContext : public ::google::protobuf::Message {
+ public:
+ SourceContext();
+ virtual ~SourceContext();
+
+ SourceContext(const SourceContext& from);
+
+ inline SourceContext& operator=(const SourceContext& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const SourceContext& default_instance();
+
+ void Swap(SourceContext* other);
+
+ // implements Message ----------------------------------------------
+
+ inline SourceContext* New() const { return New(NULL); }
+
+ SourceContext* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const SourceContext& from);
+ void MergeFrom(const SourceContext& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(SourceContext* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional string file_name = 1;
+ void clear_file_name();
+ static const int kFileNameFieldNumber = 1;
+ const ::std::string& file_name() const;
+ void set_file_name(const ::std::string& value);
+ void set_file_name(const char* value);
+ void set_file_name(const char* value, size_t size);
+ ::std::string* mutable_file_name();
+ ::std::string* release_file_name();
+ void set_allocated_file_name(::std::string* file_name);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.SourceContext)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::internal::ArenaStringPtr file_name_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fsource_5fcontext_2eproto();
+
+ void InitAsDefaultInstance();
+ static SourceContext* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// SourceContext
+
+// optional string file_name = 1;
+inline void SourceContext::clear_file_name() {
+ file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& SourceContext::file_name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.SourceContext.file_name)
+ return file_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void SourceContext::set_file_name(const ::std::string& value) {
+
+ file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.SourceContext.file_name)
+}
+inline void SourceContext::set_file_name(const char* value) {
+
+ file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.SourceContext.file_name)
+}
+inline void SourceContext::set_file_name(const char* value, size_t size) {
+
+ file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceContext.file_name)
+}
+inline ::std::string* SourceContext::mutable_file_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.SourceContext.file_name)
+ return file_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* SourceContext::release_file_name() {
+
+ return file_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void SourceContext::set_allocated_file_name(::std::string* file_name) {
+ if (file_name != NULL) {
+
+ } else {
+
+ }
+ file_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), file_name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceContext.file_name)
+}
+
+#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif // PROTOBUF_google_2fprotobuf_2fsource_5fcontext_2eproto__INCLUDED
diff --git a/src/google/protobuf/source_context.proto b/src/google/protobuf/source_context.proto
new file mode 100644
index 00000000..98d4920a
--- /dev/null
+++ b/src/google/protobuf/source_context.proto
@@ -0,0 +1,47 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+syntax = "proto3";
+
+package google.protobuf;
+
+option java_multiple_files = true;
+option java_outer_classname = "SourceContextProto";
+option java_package = "com.google.protobuf";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option objc_class_prefix = "GPB";
+
+
+// `SourceContext` represents information about the source of a
+// protobuf element, like the file in which it is defined.
+message SourceContext {
+ // The path-qualified name of the .proto file that contained the associated
+ // protobuf element. For example: `"google/protobuf/source.proto"`.
+ string file_name = 1;
+}
diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc
new file mode 100644
index 00000000..a7e2eafd
--- /dev/null
+++ b/src/google/protobuf/struct.pb.cc
@@ -0,0 +1,1455 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/struct.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "google/protobuf/struct.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* Struct_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ Struct_reflection_ = NULL;
+const ::google::protobuf::Descriptor* Struct_FieldsEntry_descriptor_ = NULL;
+const ::google::protobuf::Descriptor* Value_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ Value_reflection_ = NULL;
+struct ValueOneofInstance {
+ int null_value_;
+ double number_value_;
+ ::google::protobuf::internal::ArenaStringPtr string_value_;
+ bool bool_value_;
+ const ::google::protobuf::Struct* struct_value_;
+ const ::google::protobuf::ListValue* list_value_;
+}* Value_default_oneof_instance_ = NULL;
+const ::google::protobuf::Descriptor* ListValue_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ ListValue_reflection_ = NULL;
+const ::google::protobuf::EnumDescriptor* NullValue_descriptor_ = NULL;
+
+} // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+ const ::google::protobuf::FileDescriptor* file =
+ ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+ "google/protobuf/struct.proto");
+ GOOGLE_CHECK(file != NULL);
+ Struct_descriptor_ = file->message_type(0);
+ static const int Struct_offsets_[1] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Struct, fields_),
+ };
+ Struct_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ Struct_descriptor_,
+ Struct::default_instance_,
+ Struct_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(Struct),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Struct, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Struct, _is_default_instance_));
+ Struct_FieldsEntry_descriptor_ = Struct_descriptor_->nested_type(0);
+ Value_descriptor_ = file->message_type(1);
+ static const int Value_offsets_[7] = {
+ PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Value_default_oneof_instance_, null_value_),
+ PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Value_default_oneof_instance_, number_value_),
+ PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Value_default_oneof_instance_, string_value_),
+ PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Value_default_oneof_instance_, bool_value_),
+ PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Value_default_oneof_instance_, struct_value_),
+ PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(Value_default_oneof_instance_, list_value_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Value, kind_),
+ };
+ Value_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ Value_descriptor_,
+ Value::default_instance_,
+ Value_offsets_,
+ -1,
+ -1,
+ -1,
+ Value_default_oneof_instance_,
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Value, _oneof_case_[0]),
+ sizeof(Value),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Value, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Value, _is_default_instance_));
+ ListValue_descriptor_ = file->message_type(2);
+ static const int ListValue_offsets_[1] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ListValue, values_),
+ };
+ ListValue_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ ListValue_descriptor_,
+ ListValue::default_instance_,
+ ListValue_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(ListValue),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ListValue, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ListValue, _is_default_instance_));
+ NullValue_descriptor_ = file->enum_type(0);
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+ ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+ &protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ Struct_descriptor_, &Struct::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ Struct_FieldsEntry_descriptor_,
+ ::google::protobuf::internal::MapEntry<
+ ::std::string,
+ ::google::protobuf::Value,
+ ::google::protobuf::internal::WireFormatLite::TYPE_STRING,
+ ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE,
+ 0>::CreateDefaultInstance(
+ Struct_FieldsEntry_descriptor_));
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ Value_descriptor_, &Value::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ ListValue_descriptor_, &ListValue::default_instance());
+}
+
+} // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fstruct_2eproto() {
+ delete Struct::default_instance_;
+ delete Struct_reflection_;
+ delete Value::default_instance_;
+ delete Value_default_oneof_instance_;
+ delete Value_reflection_;
+ delete ListValue::default_instance_;
+ delete ListValue_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto() {
+ static bool already_here = false;
+ if (already_here) return;
+ already_here = true;
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+ "\n\034google/protobuf/struct.proto\022\017google.p"
+ "rotobuf\"\204\001\n\006Struct\0223\n\006fields\030\001 \003(\0132#.goo"
+ "gle.protobuf.Struct.FieldsEntry\032E\n\013Field"
+ "sEntry\022\013\n\003key\030\001 \001(\t\022%\n\005value\030\002 \001(\0132\026.goo"
+ "gle.protobuf.Value:\0028\001\"\352\001\n\005Value\0220\n\nnull"
+ "_value\030\001 \001(\0162\032.google.protobuf.NullValue"
+ "H\000\022\026\n\014number_value\030\002 \001(\001H\000\022\026\n\014string_val"
+ "ue\030\003 \001(\tH\000\022\024\n\nbool_value\030\004 \001(\010H\000\022/\n\014stru"
+ "ct_value\030\005 \001(\0132\027.google.protobuf.StructH"
+ "\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);
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+ "google/protobuf/struct.proto", &protobuf_RegisterTypes);
+ Struct::default_instance_ = new Struct();
+ Value::default_instance_ = new Value();
+ Value_default_oneof_instance_ = new ValueOneofInstance();
+ ListValue::default_instance_ = new ListValue();
+ Struct::default_instance_->InitAsDefaultInstance();
+ Value::default_instance_->InitAsDefaultInstance();
+ ListValue::default_instance_->InitAsDefaultInstance();
+ ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fstruct_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fstruct_2eproto {
+ StaticDescriptorInitializer_google_2fprotobuf_2fstruct_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+ }
+} static_descriptor_initializer_google_2fprotobuf_2fstruct_2eproto_;
+const ::google::protobuf::EnumDescriptor* NullValue_descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return NullValue_descriptor_;
+}
+bool NullValue_IsValid(int value) {
+ switch(value) {
+ case 0:
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+ GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+} // namespace
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int Struct::kFieldsFieldNumber;
+#endif // !_MSC_VER
+
+Struct::Struct()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.Struct)
+}
+
+void Struct::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+Struct::Struct(const Struct& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.Struct)
+}
+
+void Struct::SharedCtor() {
+ _is_default_instance_ = false;
+ _cached_size_ = 0;
+ fields_.SetAssignDescriptorCallback(
+ protobuf_AssignDescriptorsOnce);
+ fields_.SetEntryDescriptor(
+ &::google::protobuf::Struct_FieldsEntry_descriptor_);
+}
+
+Struct::~Struct() {
+ // @@protoc_insertion_point(destructor:google.protobuf.Struct)
+ SharedDtor();
+}
+
+void Struct::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void Struct::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Struct::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Struct_descriptor_;
+}
+
+const Struct& Struct::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+ return *default_instance_;
+}
+
+Struct* Struct::default_instance_ = NULL;
+
+Struct* Struct::New(::google::protobuf::Arena* arena) const {
+ Struct* n = new Struct;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void Struct::Clear() {
+ fields_.Clear();
+}
+
+bool Struct::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.Struct)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // map<string, .google.protobuf.Value> fields = 1;
+ case 1: {
+ if (tag == 10) {
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_fields:
+ ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry(fields_.NewEntry());
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, entry.get()));
+ (*mutable_fields())[entry->key()].Swap(entry->mutable_value());
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(10)) goto parse_loop_fields;
+ input->UnsafeDecrementRecursionDepth();
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.Struct)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.Struct)
+ return false;
+#undef DO_
+}
+
+void Struct::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.Struct)
+ // map<string, .google.protobuf.Value> fields = 1;
+ {
+ ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
+ for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
+ it = this->fields().begin();
+ it != this->fields().end(); ++it) {
+ entry.reset(fields_.NewEntryWrapper(it->first, it->second));
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 1, *entry, output);
+ }
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.Struct)
+}
+
+::google::protobuf::uint8* Struct::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Struct)
+ // map<string, .google.protobuf.Value> fields = 1;
+ {
+ ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
+ for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
+ it = this->fields().begin();
+ it != this->fields().end(); ++it) {
+ entry.reset(fields_.NewEntryWrapper(it->first, it->second));
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 1, *entry, target);
+ }
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Struct)
+ return target;
+}
+
+int Struct::ByteSize() const {
+ int total_size = 0;
+
+ // map<string, .google.protobuf.Value> fields = 1;
+ total_size += 1 * this->fields_size();
+ {
+ ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
+ for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
+ it = this->fields().begin();
+ it != this->fields().end(); ++it) {
+ entry.reset(fields_.NewEntryWrapper(it->first, it->second));
+ total_size += ::google::protobuf::internal::WireFormatLite::
+ MessageSizeNoVirtual(*entry);
+ }
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void Struct::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const Struct* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Struct>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void Struct::MergeFrom(const Struct& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ fields_.MergeFrom(from.fields_);
+}
+
+void Struct::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void Struct::CopyFrom(const Struct& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Struct::IsInitialized() const {
+
+ return true;
+}
+
+void Struct::Swap(Struct* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void Struct::InternalSwap(Struct* other) {
+ fields_.Swap(&other->fields_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Struct::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = Struct_descriptor_;
+ metadata.reflection = Struct_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Struct
+
+// map<string, .google.protobuf.Value> fields = 1;
+int Struct::fields_size() const {
+ return fields_.size();
+}
+void Struct::clear_fields() {
+ fields_.Clear();
+}
+ const ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >&
+Struct::fields() const {
+ // @@protoc_insertion_point(field_map:google.protobuf.Struct.fields)
+ return fields_.GetMap();
+}
+ ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >*
+Struct::mutable_fields() {
+ // @@protoc_insertion_point(field_mutable_map:google.protobuf.Struct.fields)
+ return fields_.MutableMap();
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int Value::kNullValueFieldNumber;
+const int Value::kNumberValueFieldNumber;
+const int Value::kStringValueFieldNumber;
+const int Value::kBoolValueFieldNumber;
+const int Value::kStructValueFieldNumber;
+const int Value::kListValueFieldNumber;
+#endif // !_MSC_VER
+
+Value::Value()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.Value)
+}
+
+void Value::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+ Value_default_oneof_instance_->null_value_ = 0;
+ Value_default_oneof_instance_->number_value_ = 0;
+ Value_default_oneof_instance_->string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ Value_default_oneof_instance_->bool_value_ = false;
+ Value_default_oneof_instance_->struct_value_ = const_cast< ::google::protobuf::Struct*>(&::google::protobuf::Struct::default_instance());
+ Value_default_oneof_instance_->list_value_ = const_cast< ::google::protobuf::ListValue*>(&::google::protobuf::ListValue::default_instance());
+}
+
+Value::Value(const Value& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.Value)
+}
+
+void Value::SharedCtor() {
+ _is_default_instance_ = false;
+ ::google::protobuf::internal::GetEmptyString();
+ _cached_size_ = 0;
+ clear_has_kind();
+}
+
+Value::~Value() {
+ // @@protoc_insertion_point(destructor:google.protobuf.Value)
+ SharedDtor();
+}
+
+void Value::SharedDtor() {
+ if (has_kind()) {
+ clear_kind();
+ }
+ if (this != default_instance_) {
+ }
+}
+
+void Value::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Value::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Value_descriptor_;
+}
+
+const Value& Value::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+ return *default_instance_;
+}
+
+Value* Value::default_instance_ = NULL;
+
+Value* Value::New(::google::protobuf::Arena* arena) const {
+ Value* n = new Value;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void Value::clear_kind() {
+ switch(kind_case()) {
+ case kNullValue: {
+ // No need to clear
+ break;
+ }
+ case kNumberValue: {
+ // No need to clear
+ break;
+ }
+ case kStringValue: {
+ kind_.string_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ break;
+ }
+ case kBoolValue: {
+ // No need to clear
+ break;
+ }
+ case kStructValue: {
+ delete kind_.struct_value_;
+ break;
+ }
+ case kListValue: {
+ delete kind_.list_value_;
+ break;
+ }
+ case KIND_NOT_SET: {
+ break;
+ }
+ }
+ _oneof_case_[0] = KIND_NOT_SET;
+}
+
+
+void Value::Clear() {
+ clear_kind();
+}
+
+bool Value::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.Value)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional .google.protobuf.NullValue null_value = 1;
+ case 1: {
+ if (tag == 8) {
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ set_null_value(static_cast< ::google::protobuf::NullValue >(value));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(17)) goto parse_number_value;
+ break;
+ }
+
+ // optional double number_value = 2;
+ case 2: {
+ if (tag == 17) {
+ parse_number_value:
+ clear_kind();
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
+ input, &kind_.number_value_)));
+ set_has_number_value();
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(26)) goto parse_string_value;
+ break;
+ }
+
+ // optional string string_value = 3;
+ case 3: {
+ if (tag == 26) {
+ parse_string_value:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_string_value()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->string_value().data(), this->string_value().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.Value.string_value");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(32)) goto parse_bool_value;
+ break;
+ }
+
+ // optional bool bool_value = 4;
+ case 4: {
+ if (tag == 32) {
+ parse_bool_value:
+ clear_kind();
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &kind_.bool_value_)));
+ set_has_bool_value();
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(42)) goto parse_struct_value;
+ break;
+ }
+
+ // optional .google.protobuf.Struct struct_value = 5;
+ case 5: {
+ if (tag == 42) {
+ parse_struct_value:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_struct_value()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(50)) goto parse_list_value;
+ break;
+ }
+
+ // optional .google.protobuf.ListValue list_value = 6;
+ case 6: {
+ if (tag == 50) {
+ parse_list_value:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_list_value()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.Value)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.Value)
+ return false;
+#undef DO_
+}
+
+void Value::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.Value)
+ // optional .google.protobuf.NullValue null_value = 1;
+ if (has_null_value()) {
+ ::google::protobuf::internal::WireFormatLite::WriteEnum(
+ 1, this->null_value(), output);
+ }
+
+ // optional double number_value = 2;
+ if (has_number_value()) {
+ ::google::protobuf::internal::WireFormatLite::WriteDouble(2, this->number_value(), output);
+ }
+
+ // optional string string_value = 3;
+ if (has_string_value()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->string_value().data(), this->string_value().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Value.string_value");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 3, this->string_value(), output);
+ }
+
+ // optional bool bool_value = 4;
+ if (has_bool_value()) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(4, this->bool_value(), output);
+ }
+
+ // optional .google.protobuf.Struct struct_value = 5;
+ if (has_struct_value()) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 5, *kind_.struct_value_, output);
+ }
+
+ // optional .google.protobuf.ListValue list_value = 6;
+ if (has_list_value()) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 6, *kind_.list_value_, output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.Value)
+}
+
+::google::protobuf::uint8* Value::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Value)
+ // optional .google.protobuf.NullValue null_value = 1;
+ if (has_null_value()) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+ 1, this->null_value(), target);
+ }
+
+ // optional double number_value = 2;
+ if (has_number_value()) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(2, this->number_value(), target);
+ }
+
+ // optional string string_value = 3;
+ if (has_string_value()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->string_value().data(), this->string_value().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Value.string_value");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 3, this->string_value(), target);
+ }
+
+ // optional bool bool_value = 4;
+ if (has_bool_value()) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(4, this->bool_value(), target);
+ }
+
+ // optional .google.protobuf.Struct struct_value = 5;
+ if (has_struct_value()) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 5, *kind_.struct_value_, target);
+ }
+
+ // optional .google.protobuf.ListValue list_value = 6;
+ if (has_list_value()) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 6, *kind_.list_value_, target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Value)
+ return target;
+}
+
+int Value::ByteSize() const {
+ int total_size = 0;
+
+ switch (kind_case()) {
+ // optional .google.protobuf.NullValue null_value = 1;
+ case kNullValue: {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::EnumSize(this->null_value());
+ break;
+ }
+ // optional double number_value = 2;
+ case kNumberValue: {
+ total_size += 1 + 8;
+ break;
+ }
+ // optional string string_value = 3;
+ case kStringValue: {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->string_value());
+ break;
+ }
+ // optional bool bool_value = 4;
+ case kBoolValue: {
+ total_size += 1 + 1;
+ break;
+ }
+ // optional .google.protobuf.Struct struct_value = 5;
+ case kStructValue: {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ *kind_.struct_value_);
+ break;
+ }
+ // optional .google.protobuf.ListValue list_value = 6;
+ case kListValue: {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ *kind_.list_value_);
+ break;
+ }
+ case KIND_NOT_SET: {
+ break;
+ }
+ }
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void Value::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const Value* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Value>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void Value::MergeFrom(const Value& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ switch (from.kind_case()) {
+ case kNullValue: {
+ set_null_value(from.null_value());
+ break;
+ }
+ case kNumberValue: {
+ set_number_value(from.number_value());
+ break;
+ }
+ case kStringValue: {
+ set_string_value(from.string_value());
+ break;
+ }
+ case kBoolValue: {
+ set_bool_value(from.bool_value());
+ break;
+ }
+ case kStructValue: {
+ mutable_struct_value()->::google::protobuf::Struct::MergeFrom(from.struct_value());
+ break;
+ }
+ case kListValue: {
+ mutable_list_value()->::google::protobuf::ListValue::MergeFrom(from.list_value());
+ break;
+ }
+ case KIND_NOT_SET: {
+ break;
+ }
+ }
+}
+
+void Value::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void Value::CopyFrom(const Value& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Value::IsInitialized() const {
+
+ return true;
+}
+
+void Value::Swap(Value* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void Value::InternalSwap(Value* other) {
+ std::swap(kind_, other->kind_);
+ std::swap(_oneof_case_[0], other->_oneof_case_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Value::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = Value_descriptor_;
+ metadata.reflection = Value_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Value
+
+// optional .google.protobuf.NullValue null_value = 1;
+bool Value::has_null_value() const {
+ return kind_case() == kNullValue;
+}
+void Value::set_has_null_value() {
+ _oneof_case_[0] = kNullValue;
+}
+void Value::clear_null_value() {
+ if (has_null_value()) {
+ kind_.null_value_ = 0;
+ clear_has_kind();
+ }
+}
+ ::google::protobuf::NullValue Value::null_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Value.null_value)
+ if (has_null_value()) {
+ return static_cast< ::google::protobuf::NullValue >(kind_.null_value_);
+ }
+ return static_cast< ::google::protobuf::NullValue >(0);
+}
+ void Value::set_null_value(::google::protobuf::NullValue value) {
+ if (!has_null_value()) {
+ clear_kind();
+ set_has_null_value();
+ }
+ kind_.null_value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Value.null_value)
+}
+
+// optional double number_value = 2;
+bool Value::has_number_value() const {
+ return kind_case() == kNumberValue;
+}
+void Value::set_has_number_value() {
+ _oneof_case_[0] = kNumberValue;
+}
+void Value::clear_number_value() {
+ if (has_number_value()) {
+ kind_.number_value_ = 0;
+ clear_has_kind();
+ }
+}
+ double Value::number_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Value.number_value)
+ if (has_number_value()) {
+ return kind_.number_value_;
+ }
+ return 0;
+}
+ void Value::set_number_value(double value) {
+ if (!has_number_value()) {
+ clear_kind();
+ set_has_number_value();
+ }
+ kind_.number_value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Value.number_value)
+}
+
+// optional string string_value = 3;
+bool Value::has_string_value() const {
+ return kind_case() == kStringValue;
+}
+void Value::set_has_string_value() {
+ _oneof_case_[0] = kStringValue;
+}
+void Value::clear_string_value() {
+ if (has_string_value()) {
+ kind_.string_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_kind();
+ }
+}
+ const ::std::string& Value::string_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Value.string_value)
+ if (has_string_value()) {
+ return kind_.string_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ return *&::google::protobuf::internal::GetEmptyStringAlreadyInited();
+}
+ void Value::set_string_value(const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value)
+ if (!has_string_value()) {
+ clear_kind();
+ set_has_string_value();
+ kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ kind_.string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value)
+}
+ void Value::set_string_value(const char* value) {
+ if (!has_string_value()) {
+ clear_kind();
+ set_has_string_value();
+ kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ kind_.string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Value.string_value)
+}
+ void Value::set_string_value(const char* value, size_t size) {
+ if (!has_string_value()) {
+ clear_kind();
+ set_has_string_value();
+ kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ kind_.string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Value.string_value)
+}
+ ::std::string* Value::mutable_string_value() {
+ if (!has_string_value()) {
+ clear_kind();
+ set_has_string_value();
+ kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Value.string_value)
+ return kind_.string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Value::release_string_value() {
+ if (has_string_value()) {
+ clear_has_kind();
+ return kind_.string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ } else {
+ return NULL;
+ }
+}
+ void Value::set_allocated_string_value(::std::string* string_value) {
+ if (!has_string_value()) {
+ kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ clear_kind();
+ if (string_value != NULL) {
+ set_has_string_value();
+ kind_.string_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ string_value);
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.string_value)
+}
+
+// optional bool bool_value = 4;
+bool Value::has_bool_value() const {
+ return kind_case() == kBoolValue;
+}
+void Value::set_has_bool_value() {
+ _oneof_case_[0] = kBoolValue;
+}
+void Value::clear_bool_value() {
+ if (has_bool_value()) {
+ kind_.bool_value_ = false;
+ clear_has_kind();
+ }
+}
+ bool Value::bool_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Value.bool_value)
+ if (has_bool_value()) {
+ return kind_.bool_value_;
+ }
+ return false;
+}
+ void Value::set_bool_value(bool value) {
+ if (!has_bool_value()) {
+ clear_kind();
+ set_has_bool_value();
+ }
+ kind_.bool_value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Value.bool_value)
+}
+
+// optional .google.protobuf.Struct struct_value = 5;
+bool Value::has_struct_value() const {
+ return kind_case() == kStructValue;
+}
+void Value::set_has_struct_value() {
+ _oneof_case_[0] = kStructValue;
+}
+void Value::clear_struct_value() {
+ if (has_struct_value()) {
+ delete kind_.struct_value_;
+ clear_has_kind();
+ }
+}
+ const ::google::protobuf::Struct& Value::struct_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Value.struct_value)
+ return has_struct_value() ? *kind_.struct_value_
+ : ::google::protobuf::Struct::default_instance();
+}
+ ::google::protobuf::Struct* Value::mutable_struct_value() {
+ if (!has_struct_value()) {
+ clear_kind();
+ set_has_struct_value();
+ kind_.struct_value_ = new ::google::protobuf::Struct;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Value.struct_value)
+ return kind_.struct_value_;
+}
+ ::google::protobuf::Struct* Value::release_struct_value() {
+ if (has_struct_value()) {
+ clear_has_kind();
+ ::google::protobuf::Struct* temp = kind_.struct_value_;
+ kind_.struct_value_ = NULL;
+ return temp;
+ } else {
+ return NULL;
+ }
+}
+ void Value::set_allocated_struct_value(::google::protobuf::Struct* struct_value) {
+ clear_kind();
+ if (struct_value) {
+ set_has_struct_value();
+ kind_.struct_value_ = struct_value;
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.struct_value)
+}
+
+// optional .google.protobuf.ListValue list_value = 6;
+bool Value::has_list_value() const {
+ return kind_case() == kListValue;
+}
+void Value::set_has_list_value() {
+ _oneof_case_[0] = kListValue;
+}
+void Value::clear_list_value() {
+ if (has_list_value()) {
+ delete kind_.list_value_;
+ clear_has_kind();
+ }
+}
+ const ::google::protobuf::ListValue& Value::list_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Value.list_value)
+ return has_list_value() ? *kind_.list_value_
+ : ::google::protobuf::ListValue::default_instance();
+}
+ ::google::protobuf::ListValue* Value::mutable_list_value() {
+ if (!has_list_value()) {
+ clear_kind();
+ set_has_list_value();
+ kind_.list_value_ = new ::google::protobuf::ListValue;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Value.list_value)
+ return kind_.list_value_;
+}
+ ::google::protobuf::ListValue* Value::release_list_value() {
+ if (has_list_value()) {
+ clear_has_kind();
+ ::google::protobuf::ListValue* temp = kind_.list_value_;
+ kind_.list_value_ = NULL;
+ return temp;
+ } else {
+ return NULL;
+ }
+}
+ void Value::set_allocated_list_value(::google::protobuf::ListValue* list_value) {
+ clear_kind();
+ if (list_value) {
+ set_has_list_value();
+ kind_.list_value_ = list_value;
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.list_value)
+}
+
+bool Value::has_kind() const {
+ return kind_case() != KIND_NOT_SET;
+}
+void Value::clear_has_kind() {
+ _oneof_case_[0] = KIND_NOT_SET;
+}
+Value::KindCase Value::kind_case() const {
+ return Value::KindCase(_oneof_case_[0]);
+}
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int ListValue::kValuesFieldNumber;
+#endif // !_MSC_VER
+
+ListValue::ListValue()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.ListValue)
+}
+
+void ListValue::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+ListValue::ListValue(const ListValue& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.ListValue)
+}
+
+void ListValue::SharedCtor() {
+ _is_default_instance_ = false;
+ _cached_size_ = 0;
+}
+
+ListValue::~ListValue() {
+ // @@protoc_insertion_point(destructor:google.protobuf.ListValue)
+ SharedDtor();
+}
+
+void ListValue::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void ListValue::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* ListValue::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return ListValue_descriptor_;
+}
+
+const ListValue& ListValue::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+ return *default_instance_;
+}
+
+ListValue* ListValue::default_instance_ = NULL;
+
+ListValue* ListValue::New(::google::protobuf::Arena* arena) const {
+ ListValue* n = new ListValue;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void ListValue::Clear() {
+ values_.Clear();
+}
+
+bool ListValue::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.ListValue)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // repeated .google.protobuf.Value values = 1;
+ case 1: {
+ if (tag == 10) {
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_values:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ input, add_values()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(10)) goto parse_loop_values;
+ input->UnsafeDecrementRecursionDepth();
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.ListValue)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.ListValue)
+ return false;
+#undef DO_
+}
+
+void ListValue::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.ListValue)
+ // repeated .google.protobuf.Value values = 1;
+ for (unsigned int i = 0, n = this->values_size(); i < n; i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 1, this->values(i), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.ListValue)
+}
+
+::google::protobuf::uint8* ListValue::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ListValue)
+ // repeated .google.protobuf.Value values = 1;
+ for (unsigned int i = 0, n = this->values_size(); i < n; i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 1, this->values(i), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ListValue)
+ return target;
+}
+
+int ListValue::ByteSize() const {
+ int total_size = 0;
+
+ // repeated .google.protobuf.Value values = 1;
+ total_size += 1 * this->values_size();
+ for (int i = 0; i < this->values_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->values(i));
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void ListValue::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const ListValue* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const ListValue>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void ListValue::MergeFrom(const ListValue& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ values_.MergeFrom(from.values_);
+}
+
+void ListValue::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void ListValue::CopyFrom(const ListValue& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool ListValue::IsInitialized() const {
+
+ return true;
+}
+
+void ListValue::Swap(ListValue* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void ListValue::InternalSwap(ListValue* other) {
+ values_.UnsafeArenaSwap(&other->values_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata ListValue::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = ListValue_descriptor_;
+ metadata.reflection = ListValue_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// ListValue
+
+// repeated .google.protobuf.Value values = 1;
+int ListValue::values_size() const {
+ return values_.size();
+}
+void ListValue::clear_values() {
+ values_.Clear();
+}
+ const ::google::protobuf::Value& ListValue::values(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.ListValue.values)
+ return values_.Get(index);
+}
+ ::google::protobuf::Value* ListValue::mutable_values(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.ListValue.values)
+ return values_.Mutable(index);
+}
+ ::google::protobuf::Value* ListValue::add_values() {
+ // @@protoc_insertion_point(field_add:google.protobuf.ListValue.values)
+ return values_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >&
+ListValue::values() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.ListValue.values)
+ return values_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >*
+ListValue::mutable_values() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.ListValue.values)
+ return &values_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h
new file mode 100644
index 00000000..2889c8fe
--- /dev/null
+++ b/src/google/protobuf/struct.pb.h
@@ -0,0 +1,764 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/struct.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fstruct_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fstruct_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/map.h>
+#include <google/protobuf/map_field_inl.h>
+#include <google/protobuf/generated_enum_reflection.h>
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fstruct_2eproto();
+
+class Struct;
+class Value;
+class ListValue;
+
+enum NullValue {
+ NULL_VALUE = 0,
+ NullValue_INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,
+ NullValue_INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max
+};
+LIBPROTOBUF_EXPORT bool NullValue_IsValid(int value);
+const NullValue NullValue_MIN = NULL_VALUE;
+const NullValue NullValue_MAX = NULL_VALUE;
+const int NullValue_ARRAYSIZE = NullValue_MAX + 1;
+
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* NullValue_descriptor();
+inline const ::std::string& NullValue_Name(NullValue value) {
+ return ::google::protobuf::internal::NameOfEnum(
+ NullValue_descriptor(), value);
+}
+inline bool NullValue_Parse(
+ const ::std::string& name, NullValue* value) {
+ return ::google::protobuf::internal::ParseNamedEnum<NullValue>(
+ NullValue_descriptor(), name, value);
+}
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT Struct : public ::google::protobuf::Message {
+ public:
+ Struct();
+ virtual ~Struct();
+
+ Struct(const Struct& from);
+
+ inline Struct& operator=(const Struct& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const Struct& default_instance();
+
+ void Swap(Struct* other);
+
+ // implements Message ----------------------------------------------
+
+ inline Struct* New() const { return New(NULL); }
+
+ Struct* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const Struct& from);
+ void MergeFrom(const Struct& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(Struct* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+
+ // accessors -------------------------------------------------------
+
+ // map<string, .google.protobuf.Value> fields = 1;
+ int fields_size() const;
+ void clear_fields();
+ static const int kFieldsFieldNumber = 1;
+ const ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >&
+ fields() const;
+ ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >*
+ mutable_fields();
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.Struct)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ typedef ::google::protobuf::internal::MapEntryLite<
+ ::std::string, ::google::protobuf::Value,
+ ::google::protobuf::internal::WireFormatLite::TYPE_STRING,
+ ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE,
+ 0 >
+ Struct_FieldsEntry;
+ ::google::protobuf::internal::MapField<
+ ::std::string, ::google::protobuf::Value,
+ ::google::protobuf::internal::WireFormatLite::TYPE_STRING,
+ ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE,
+ 0 > fields_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fstruct_2eproto();
+
+ void InitAsDefaultInstance();
+ static Struct* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT Value : public ::google::protobuf::Message {
+ public:
+ Value();
+ virtual ~Value();
+
+ Value(const Value& from);
+
+ inline Value& operator=(const Value& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const Value& default_instance();
+
+ enum KindCase {
+ kNullValue = 1,
+ kNumberValue = 2,
+ kStringValue = 3,
+ kBoolValue = 4,
+ kStructValue = 5,
+ kListValue = 6,
+ KIND_NOT_SET = 0,
+ };
+
+ void Swap(Value* other);
+
+ // implements Message ----------------------------------------------
+
+ inline Value* New() const { return New(NULL); }
+
+ Value* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const Value& from);
+ void MergeFrom(const Value& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(Value* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional .google.protobuf.NullValue null_value = 1;
+ private:
+ bool has_null_value() const;
+ public:
+ void clear_null_value();
+ static const int kNullValueFieldNumber = 1;
+ ::google::protobuf::NullValue null_value() const;
+ void set_null_value(::google::protobuf::NullValue value);
+
+ // optional double number_value = 2;
+ private:
+ bool has_number_value() const;
+ public:
+ void clear_number_value();
+ static const int kNumberValueFieldNumber = 2;
+ double number_value() const;
+ void set_number_value(double value);
+
+ // optional string string_value = 3;
+ private:
+ bool has_string_value() const;
+ public:
+ void clear_string_value();
+ static const int kStringValueFieldNumber = 3;
+ const ::std::string& string_value() const;
+ void set_string_value(const ::std::string& value);
+ void set_string_value(const char* value);
+ void set_string_value(const char* value, size_t size);
+ ::std::string* mutable_string_value();
+ ::std::string* release_string_value();
+ void set_allocated_string_value(::std::string* string_value);
+
+ // optional bool bool_value = 4;
+ private:
+ bool has_bool_value() const;
+ public:
+ void clear_bool_value();
+ static const int kBoolValueFieldNumber = 4;
+ bool bool_value() const;
+ void set_bool_value(bool value);
+
+ // optional .google.protobuf.Struct struct_value = 5;
+ bool has_struct_value() const;
+ void clear_struct_value();
+ static const int kStructValueFieldNumber = 5;
+ const ::google::protobuf::Struct& struct_value() const;
+ ::google::protobuf::Struct* mutable_struct_value();
+ ::google::protobuf::Struct* release_struct_value();
+ void set_allocated_struct_value(::google::protobuf::Struct* struct_value);
+
+ // optional .google.protobuf.ListValue list_value = 6;
+ bool has_list_value() const;
+ void clear_list_value();
+ static const int kListValueFieldNumber = 6;
+ const ::google::protobuf::ListValue& list_value() const;
+ ::google::protobuf::ListValue* mutable_list_value();
+ ::google::protobuf::ListValue* release_list_value();
+ void set_allocated_list_value(::google::protobuf::ListValue* list_value);
+
+ KindCase kind_case() const;
+ // @@protoc_insertion_point(class_scope:google.protobuf.Value)
+ private:
+ inline void set_has_null_value();
+ inline void set_has_number_value();
+ inline void set_has_string_value();
+ inline void set_has_bool_value();
+ inline void set_has_struct_value();
+ inline void set_has_list_value();
+
+ inline bool has_kind() const;
+ void clear_kind();
+ inline void clear_has_kind();
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ union KindUnion {
+ KindUnion() {}
+ int null_value_;
+ double number_value_;
+ ::google::protobuf::internal::ArenaStringPtr string_value_;
+ bool bool_value_;
+ ::google::protobuf::Struct* struct_value_;
+ ::google::protobuf::ListValue* list_value_;
+ } kind_;
+ mutable int _cached_size_;
+ ::google::protobuf::uint32 _oneof_case_[1];
+
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fstruct_2eproto();
+
+ void InitAsDefaultInstance();
+ static Value* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT ListValue : public ::google::protobuf::Message {
+ public:
+ ListValue();
+ virtual ~ListValue();
+
+ ListValue(const ListValue& from);
+
+ inline ListValue& operator=(const ListValue& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const ListValue& default_instance();
+
+ void Swap(ListValue* other);
+
+ // implements Message ----------------------------------------------
+
+ inline ListValue* New() const { return New(NULL); }
+
+ ListValue* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const ListValue& from);
+ void MergeFrom(const ListValue& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(ListValue* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // repeated .google.protobuf.Value values = 1;
+ int values_size() const;
+ void clear_values();
+ static const int kValuesFieldNumber = 1;
+ const ::google::protobuf::Value& values(int index) const;
+ ::google::protobuf::Value* mutable_values(int index);
+ ::google::protobuf::Value* add_values();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >&
+ values() const;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >*
+ mutable_values();
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.ListValue)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value > values_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fstruct_2eproto();
+
+ void InitAsDefaultInstance();
+ static ListValue* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// Struct
+
+// map<string, .google.protobuf.Value> fields = 1;
+inline int Struct::fields_size() const {
+ return fields_.size();
+}
+inline void Struct::clear_fields() {
+ fields_.Clear();
+}
+inline const ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >&
+Struct::fields() const {
+ // @@protoc_insertion_point(field_map:google.protobuf.Struct.fields)
+ return fields_.GetMap();
+}
+inline ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >*
+Struct::mutable_fields() {
+ // @@protoc_insertion_point(field_mutable_map:google.protobuf.Struct.fields)
+ return fields_.MutableMap();
+}
+
+// -------------------------------------------------------------------
+
+// Value
+
+// optional .google.protobuf.NullValue null_value = 1;
+inline bool Value::has_null_value() const {
+ return kind_case() == kNullValue;
+}
+inline void Value::set_has_null_value() {
+ _oneof_case_[0] = kNullValue;
+}
+inline void Value::clear_null_value() {
+ if (has_null_value()) {
+ kind_.null_value_ = 0;
+ clear_has_kind();
+ }
+}
+inline ::google::protobuf::NullValue Value::null_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Value.null_value)
+ if (has_null_value()) {
+ return static_cast< ::google::protobuf::NullValue >(kind_.null_value_);
+ }
+ return static_cast< ::google::protobuf::NullValue >(0);
+}
+inline void Value::set_null_value(::google::protobuf::NullValue value) {
+ if (!has_null_value()) {
+ clear_kind();
+ set_has_null_value();
+ }
+ kind_.null_value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Value.null_value)
+}
+
+// optional double number_value = 2;
+inline bool Value::has_number_value() const {
+ return kind_case() == kNumberValue;
+}
+inline void Value::set_has_number_value() {
+ _oneof_case_[0] = kNumberValue;
+}
+inline void Value::clear_number_value() {
+ if (has_number_value()) {
+ kind_.number_value_ = 0;
+ clear_has_kind();
+ }
+}
+inline double Value::number_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Value.number_value)
+ if (has_number_value()) {
+ return kind_.number_value_;
+ }
+ return 0;
+}
+inline void Value::set_number_value(double value) {
+ if (!has_number_value()) {
+ clear_kind();
+ set_has_number_value();
+ }
+ kind_.number_value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Value.number_value)
+}
+
+// optional string string_value = 3;
+inline bool Value::has_string_value() const {
+ return kind_case() == kStringValue;
+}
+inline void Value::set_has_string_value() {
+ _oneof_case_[0] = kStringValue;
+}
+inline void Value::clear_string_value() {
+ if (has_string_value()) {
+ kind_.string_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_kind();
+ }
+}
+inline const ::std::string& Value::string_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Value.string_value)
+ if (has_string_value()) {
+ return kind_.string_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ return *&::google::protobuf::internal::GetEmptyStringAlreadyInited();
+}
+inline void Value::set_string_value(const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value)
+ if (!has_string_value()) {
+ clear_kind();
+ set_has_string_value();
+ kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ kind_.string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value)
+}
+inline void Value::set_string_value(const char* value) {
+ if (!has_string_value()) {
+ clear_kind();
+ set_has_string_value();
+ kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ kind_.string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Value.string_value)
+}
+inline void Value::set_string_value(const char* value, size_t size) {
+ if (!has_string_value()) {
+ clear_kind();
+ set_has_string_value();
+ kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ kind_.string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Value.string_value)
+}
+inline ::std::string* Value::mutable_string_value() {
+ if (!has_string_value()) {
+ clear_kind();
+ set_has_string_value();
+ kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Value.string_value)
+ return kind_.string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Value::release_string_value() {
+ if (has_string_value()) {
+ clear_has_kind();
+ return kind_.string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ } else {
+ return NULL;
+ }
+}
+inline void Value::set_allocated_string_value(::std::string* string_value) {
+ if (!has_string_value()) {
+ kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ clear_kind();
+ if (string_value != NULL) {
+ set_has_string_value();
+ kind_.string_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ string_value);
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.string_value)
+}
+
+// optional bool bool_value = 4;
+inline bool Value::has_bool_value() const {
+ return kind_case() == kBoolValue;
+}
+inline void Value::set_has_bool_value() {
+ _oneof_case_[0] = kBoolValue;
+}
+inline void Value::clear_bool_value() {
+ if (has_bool_value()) {
+ kind_.bool_value_ = false;
+ clear_has_kind();
+ }
+}
+inline bool Value::bool_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Value.bool_value)
+ if (has_bool_value()) {
+ return kind_.bool_value_;
+ }
+ return false;
+}
+inline void Value::set_bool_value(bool value) {
+ if (!has_bool_value()) {
+ clear_kind();
+ set_has_bool_value();
+ }
+ kind_.bool_value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Value.bool_value)
+}
+
+// optional .google.protobuf.Struct struct_value = 5;
+inline bool Value::has_struct_value() const {
+ return kind_case() == kStructValue;
+}
+inline void Value::set_has_struct_value() {
+ _oneof_case_[0] = kStructValue;
+}
+inline void Value::clear_struct_value() {
+ if (has_struct_value()) {
+ delete kind_.struct_value_;
+ clear_has_kind();
+ }
+}
+inline const ::google::protobuf::Struct& Value::struct_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Value.struct_value)
+ return has_struct_value() ? *kind_.struct_value_
+ : ::google::protobuf::Struct::default_instance();
+}
+inline ::google::protobuf::Struct* Value::mutable_struct_value() {
+ if (!has_struct_value()) {
+ clear_kind();
+ set_has_struct_value();
+ kind_.struct_value_ = new ::google::protobuf::Struct;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Value.struct_value)
+ return kind_.struct_value_;
+}
+inline ::google::protobuf::Struct* Value::release_struct_value() {
+ if (has_struct_value()) {
+ clear_has_kind();
+ ::google::protobuf::Struct* temp = kind_.struct_value_;
+ kind_.struct_value_ = NULL;
+ return temp;
+ } else {
+ return NULL;
+ }
+}
+inline void Value::set_allocated_struct_value(::google::protobuf::Struct* struct_value) {
+ clear_kind();
+ if (struct_value) {
+ set_has_struct_value();
+ kind_.struct_value_ = struct_value;
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.struct_value)
+}
+
+// optional .google.protobuf.ListValue list_value = 6;
+inline bool Value::has_list_value() const {
+ return kind_case() == kListValue;
+}
+inline void Value::set_has_list_value() {
+ _oneof_case_[0] = kListValue;
+}
+inline void Value::clear_list_value() {
+ if (has_list_value()) {
+ delete kind_.list_value_;
+ clear_has_kind();
+ }
+}
+inline const ::google::protobuf::ListValue& Value::list_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Value.list_value)
+ return has_list_value() ? *kind_.list_value_
+ : ::google::protobuf::ListValue::default_instance();
+}
+inline ::google::protobuf::ListValue* Value::mutable_list_value() {
+ if (!has_list_value()) {
+ clear_kind();
+ set_has_list_value();
+ kind_.list_value_ = new ::google::protobuf::ListValue;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Value.list_value)
+ return kind_.list_value_;
+}
+inline ::google::protobuf::ListValue* Value::release_list_value() {
+ if (has_list_value()) {
+ clear_has_kind();
+ ::google::protobuf::ListValue* temp = kind_.list_value_;
+ kind_.list_value_ = NULL;
+ return temp;
+ } else {
+ return NULL;
+ }
+}
+inline void Value::set_allocated_list_value(::google::protobuf::ListValue* list_value) {
+ clear_kind();
+ if (list_value) {
+ set_has_list_value();
+ kind_.list_value_ = list_value;
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.list_value)
+}
+
+inline bool Value::has_kind() const {
+ return kind_case() != KIND_NOT_SET;
+}
+inline void Value::clear_has_kind() {
+ _oneof_case_[0] = KIND_NOT_SET;
+}
+inline Value::KindCase Value::kind_case() const {
+ return Value::KindCase(_oneof_case_[0]);
+}
+// -------------------------------------------------------------------
+
+// ListValue
+
+// repeated .google.protobuf.Value values = 1;
+inline int ListValue::values_size() const {
+ return values_.size();
+}
+inline void ListValue::clear_values() {
+ values_.Clear();
+}
+inline const ::google::protobuf::Value& ListValue::values(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.ListValue.values)
+ return values_.Get(index);
+}
+inline ::google::protobuf::Value* ListValue::mutable_values(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.ListValue.values)
+ return values_.Mutable(index);
+}
+inline ::google::protobuf::Value* ListValue::add_values() {
+ // @@protoc_insertion_point(field_add:google.protobuf.ListValue.values)
+ return values_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >&
+ListValue::values() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.ListValue.values)
+ return values_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >*
+ListValue::mutable_values() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.ListValue.values)
+ return &values_;
+}
+
+#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+#ifndef SWIG
+namespace google {
+namespace protobuf {
+
+template <> struct is_proto_enum< ::google::protobuf::NullValue> : ::google::protobuf::internal::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::NullValue>() {
+ return ::google::protobuf::NullValue_descriptor();
+}
+
+} // namespace protobuf
+} // namespace google
+#endif // SWIG
+
+// @@protoc_insertion_point(global_scope)
+
+#endif // PROTOBUF_google_2fprotobuf_2fstruct_2eproto__INCLUDED
diff --git a/src/google/protobuf/struct.proto b/src/google/protobuf/struct.proto
new file mode 100644
index 00000000..4ff10cd0
--- /dev/null
+++ b/src/google/protobuf/struct.proto
@@ -0,0 +1,90 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+syntax = "proto3";
+
+package google.protobuf;
+
+option java_generate_equals_and_hash = true;
+option java_multiple_files = true;
+option java_outer_classname = "StructProto";
+option java_package = "com.google.protobuf";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option objc_class_prefix = "GPB";
+
+
+// `Struct` represents a structured data value, consisting of fields
+// which map to dynamically typed values. In some languages, `Struct`
+// might be supported by a native representation. For example, in
+// scripting languages like JS a struct is represented as an
+// object. The details of that representation are described together
+// with the proto support for the language.
+message Struct {
+ // Map of dynamically typed values.
+ map<string, Value> fields = 1;
+}
+
+// `Value` represents a dynamically typed value which can be either
+// null, a number, a string, a boolean, a recursive struct value, or a
+// list of values. A producer of value is expected to set one of that
+// variants, absence of any variant indicates an error.
+message Value {
+ oneof kind {
+ // Represents a null value.
+ NullValue null_value = 1;
+
+ // Represents a double value.
+ double number_value = 2;
+
+ // Represents a string value.
+ string string_value = 3;
+
+ // Represents a boolean value.
+ bool bool_value = 4;
+
+ // Represents a structured value.
+ Struct struct_value = 5;
+
+ // Represents a repeated `Value`.
+ ListValue list_value = 6;
+ }
+}
+
+// `ListValue` is a wrapper around a repeated field of values.
+message ListValue {
+ // Repeated field of dynamically typed values.
+ repeated Value values = 1;
+}
+
+// `NullValue` is a singleton enumeration to represent the null
+// value for the `Value` type union.
+enum NullValue {
+ // Null value.
+ NULL_VALUE = 0;
+}
diff --git a/src/google/protobuf/stubs/atomicops.h b/src/google/protobuf/stubs/atomicops.h
index bbe2d845..cd20caac 100644
--- a/src/google/protobuf/stubs/atomicops.h
+++ b/src/google/protobuf/stubs/atomicops.h
@@ -56,6 +56,7 @@
// Don't include this file for people not concerned about thread safety.
#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/platform_macros.h>
namespace google {
diff --git a/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h b/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h
index dd7abf6f..a0116a60 100644
--- a/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h
+++ b/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h
@@ -61,8 +61,8 @@ inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
- __atomic_compare_exchange(ptr, &old_value, &new_value, true,
- __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
+ __atomic_compare_exchange_n(ptr, &old_value, new_value, true,
+ __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
return old_value;
}
diff --git a/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h b/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h
index e3cd14cf..f5837c9e 100644
--- a/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h
+++ b/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h
@@ -65,7 +65,7 @@ inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
"2:\n"
".set pop\n"
: "=&r" (prev), "=m" (*ptr), "=&r" (tmp)
- : "Ir" (old_value), "r" (new_value), "m" (*ptr)
+ : "r" (old_value), "r" (new_value), "m" (*ptr)
: "memory");
return prev;
}
@@ -197,7 +197,7 @@ inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
"2:\n"
".set pop\n"
: "=&r" (prev), "=m" (*ptr), "=&r" (tmp)
- : "Ir" (old_value), "r" (new_value), "m" (*ptr)
+ : "r" (old_value), "r" (new_value), "m" (*ptr)
: "memory");
return prev;
}
diff --git a/src/google/protobuf/stubs/atomicops_internals_pnacl.h b/src/google/protobuf/stubs/atomicops_internals_pnacl.h
index b10ac02c..3b314fd0 100644
--- a/src/google/protobuf/stubs/atomicops_internals_pnacl.h
+++ b/src/google/protobuf/stubs/atomicops_internals_pnacl.h
@@ -33,39 +33,197 @@
#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_
#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_
+#include <atomic>
+
namespace google {
namespace protobuf {
namespace internal {
+// This implementation is transitional and maintains the original API for
+// atomicops.h. This requires casting memory locations to the atomic types, and
+// assumes that the API and the C++11 implementation are layout-compatible,
+// which isn't true for all implementations or hardware platforms. The static
+// assertion should detect this issue, were it to fire then this header
+// shouldn't be used.
+//
+// TODO(jfb) If this header manages to stay committed then the API should be
+// modified, and all call sites updated.
+typedef volatile std::atomic<Atomic32>* AtomicLocation32;
+static_assert(sizeof(*(AtomicLocation32) nullptr) == sizeof(Atomic32),
+ "incompatible 32-bit atomic layout");
+
+inline void MemoryBarrier() {
+#if defined(__GLIBCXX__)
+ // Work around libstdc++ bug 51038 where atomic_thread_fence was declared but
+ // not defined, leading to the linker complaining about undefined references.
+ __atomic_thread_fence(std::memory_order_seq_cst);
+#else
+ std::atomic_thread_fence(std::memory_order_seq_cst);
+#endif
+}
+
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
- return __sync_val_compare_and_swap(ptr, old_value, new_value);
+ ((AtomicLocation32)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_relaxed,
+ std::memory_order_relaxed);
+ return old_value;
}
-inline void MemoryBarrier() {
- __sync_synchronize();
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+ Atomic32 new_value) {
+ return ((AtomicLocation32)ptr)
+ ->exchange(new_value, std::memory_order_relaxed);
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ return increment +
+ ((AtomicLocation32)ptr)
+ ->fetch_add(increment, std::memory_order_relaxed);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ return increment + ((AtomicLocation32)ptr)->fetch_add(increment);
}
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
- Atomic32 ret = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+ ((AtomicLocation32)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_acquire,
+ std::memory_order_acquire);
+ return old_value;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+ Atomic32 old_value,
+ Atomic32 new_value) {
+ ((AtomicLocation32)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_release,
+ std::memory_order_relaxed);
+ return old_value;
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+ ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
MemoryBarrier();
- return ret;
}
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
- MemoryBarrier();
- *ptr = value;
+ ((AtomicLocation32)ptr)->store(value, std::memory_order_release);
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+ return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
}
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
- Atomic32 value = *ptr;
+ return ((AtomicLocation32)ptr)->load(std::memory_order_acquire);
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+ MemoryBarrier();
+ return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
+}
+
+#if defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
+
+typedef volatile std::atomic<Atomic64>* AtomicLocation64;
+static_assert(sizeof(*(AtomicLocation64) nullptr) == sizeof(Atomic64),
+ "incompatible 64-bit atomic layout");
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+ Atomic64 old_value,
+ Atomic64 new_value) {
+ ((AtomicLocation64)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_relaxed,
+ std::memory_order_relaxed);
+ return old_value;
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+ Atomic64 new_value) {
+ return ((AtomicLocation64)ptr)
+ ->exchange(new_value, std::memory_order_relaxed);
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ return increment +
+ ((AtomicLocation64)ptr)
+ ->fetch_add(increment, std::memory_order_relaxed);
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ return increment + ((AtomicLocation64)ptr)->fetch_add(increment);
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+ Atomic64 old_value,
+ Atomic64 new_value) {
+ ((AtomicLocation64)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_acquire,
+ std::memory_order_acquire);
+ return old_value;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+ Atomic64 old_value,
+ Atomic64 new_value) {
+ ((AtomicLocation64)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_release,
+ std::memory_order_relaxed);
+ return old_value;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+ ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
MemoryBarrier();
- return value;
}
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+ ((AtomicLocation64)ptr)->store(value, std::memory_order_release);
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+ return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+ return ((AtomicLocation64)ptr)->load(std::memory_order_acquire);
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+ MemoryBarrier();
+ return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
+}
+
+#endif // defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/stubs/bytestream.cc b/src/google/protobuf/stubs/bytestream.cc
new file mode 100644
index 00000000..f4af6a50
--- /dev/null
+++ b/src/google/protobuf/stubs/bytestream.cc
@@ -0,0 +1,196 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/stubs/bytestream.h>
+
+#include <string.h>
+#include <algorithm>
+
+namespace google {
+namespace protobuf {
+namespace strings {
+
+void ByteSource::CopyTo(ByteSink* sink, size_t n) {
+ while (n > 0) {
+ StringPiece fragment = Peek();
+ if (fragment.empty()) {
+ GOOGLE_LOG(DFATAL) << "ByteSource::CopyTo() overran input.";
+ break;
+ }
+ std::size_t fragment_size = std::min<std::size_t>(n, fragment.size());
+ sink->Append(fragment.data(), fragment_size);
+ Skip(fragment_size);
+ n -= fragment_size;
+ }
+}
+
+void ByteSink::Flush() {}
+
+void UncheckedArrayByteSink::Append(const char* data, size_t n) {
+ if (data != dest_) {
+ // Catch cases where the pointer returned by GetAppendBuffer() was modified.
+ GOOGLE_DCHECK(!(dest_ <= data && data < (dest_ + n)))
+ << "Append() data[] overlaps with dest_[]";
+ memcpy(dest_, data, n);
+ }
+ dest_ += n;
+}
+
+CheckedArrayByteSink::CheckedArrayByteSink(char* outbuf, size_t capacity)
+ : outbuf_(outbuf), capacity_(capacity), size_(0), overflowed_(false) {
+}
+
+void CheckedArrayByteSink::Append(const char* bytes, size_t n) {
+ size_t available = capacity_ - size_;
+ if (n > available) {
+ n = available;
+ overflowed_ = true;
+ }
+ if (n > 0 && bytes != (outbuf_ + size_)) {
+ // Catch cases where the pointer returned by GetAppendBuffer() was modified.
+ GOOGLE_DCHECK(!(outbuf_ <= bytes && bytes < (outbuf_ + capacity_)))
+ << "Append() bytes[] overlaps with outbuf_[]";
+ memcpy(outbuf_ + size_, bytes, n);
+ }
+ size_ += n;
+}
+
+GrowingArrayByteSink::GrowingArrayByteSink(size_t estimated_size)
+ : capacity_(estimated_size),
+ buf_(new char[estimated_size]),
+ size_(0) {
+}
+
+GrowingArrayByteSink::~GrowingArrayByteSink() {
+ delete[] buf_; // Just in case the user didn't call GetBuffer.
+}
+
+void GrowingArrayByteSink::Append(const char* bytes, size_t n) {
+ size_t available = capacity_ - size_;
+ if (bytes != (buf_ + size_)) {
+ // Catch cases where the pointer returned by GetAppendBuffer() was modified.
+ // We need to test for this before calling Expand() which may reallocate.
+ GOOGLE_DCHECK(!(buf_ <= bytes && bytes < (buf_ + capacity_)))
+ << "Append() bytes[] overlaps with buf_[]";
+ }
+ if (n > available) {
+ Expand(n - available);
+ }
+ if (n > 0 && bytes != (buf_ + size_)) {
+ memcpy(buf_ + size_, bytes, n);
+ }
+ size_ += n;
+}
+
+char* GrowingArrayByteSink::GetBuffer(size_t* nbytes) {
+ ShrinkToFit();
+ char* b = buf_;
+ *nbytes = size_;
+ buf_ = NULL;
+ size_ = capacity_ = 0;
+ return b;
+}
+
+void GrowingArrayByteSink::Expand(size_t amount) { // Expand by at least 50%.
+ size_t new_capacity = std::max(capacity_ + amount, (3 * capacity_) / 2);
+ char* bigger = new char[new_capacity];
+ memcpy(bigger, buf_, size_);
+ delete[] buf_;
+ buf_ = bigger;
+ capacity_ = new_capacity;
+}
+
+void GrowingArrayByteSink::ShrinkToFit() {
+ // Shrink only if the buffer is large and size_ is less than 3/4
+ // of capacity_.
+ if (capacity_ > 256 && size_ < (3 * capacity_) / 4) {
+ char* just_enough = new char[size_];
+ memcpy(just_enough, buf_, size_);
+ delete[] buf_;
+ buf_ = just_enough;
+ capacity_ = size_;
+ }
+}
+
+void StringByteSink::Append(const char* data, size_t n) {
+ dest_->append(data, n);
+}
+
+size_t ArrayByteSource::Available() const {
+ return input_.size();
+}
+
+StringPiece ArrayByteSource::Peek() {
+ return input_;
+}
+
+void ArrayByteSource::Skip(size_t n) {
+ GOOGLE_DCHECK_LE(n, input_.size());
+ input_.remove_prefix(n);
+}
+
+LimitByteSource::LimitByteSource(ByteSource *source, size_t limit)
+ : source_(source),
+ limit_(limit) {
+}
+
+size_t LimitByteSource::Available() const {
+ size_t available = source_->Available();
+ if (available > limit_) {
+ available = limit_;
+ }
+
+ return available;
+}
+
+StringPiece LimitByteSource::Peek() {
+ StringPiece piece(source_->Peek());
+ if (piece.size() > limit_) {
+ piece.set(piece.data(), limit_);
+ }
+
+ return piece;
+}
+
+void LimitByteSource::Skip(size_t n) {
+ GOOGLE_DCHECK_LE(n, limit_);
+ source_->Skip(n);
+ limit_ -= n;
+}
+
+void LimitByteSource::CopyTo(ByteSink *sink, size_t n) {
+ GOOGLE_DCHECK_LE(n, limit_);
+ source_->CopyTo(sink, n);
+ limit_ -= n;
+}
+
+} // namespace strings
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/bytestream.h b/src/google/protobuf/stubs/bytestream.h
new file mode 100644
index 00000000..de8e0204
--- /dev/null
+++ b/src/google/protobuf/stubs/bytestream.h
@@ -0,0 +1,348 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file declares the ByteSink and ByteSource abstract interfaces. These
+// interfaces represent objects that consume (ByteSink) or produce (ByteSource)
+// a sequence of bytes. Using these abstract interfaces in your APIs can help
+// make your code work with a variety of input and output types.
+//
+// This file also declares the following commonly used implementations of these
+// interfaces.
+//
+// ByteSink:
+// UncheckedArrayByteSink Writes to an array, without bounds checking
+// CheckedArrayByteSink Writes to an array, with bounds checking
+// GrowingArrayByteSink Allocates and writes to a growable buffer
+// StringByteSink Writes to an STL string
+// NullByteSink Consumes a never-ending stream of bytes
+//
+// ByteSource:
+// ArrayByteSource Reads from an array or string/StringPiece
+// LimitedByteSource Limits the number of bytes read from an
+
+#ifndef GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_
+#define GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_
+
+#include <stddef.h>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
+
+class CordByteSink;
+class MemBlock;
+
+namespace google {
+namespace protobuf {
+namespace strings {
+
+// An abstract interface for an object that consumes a sequence of bytes. This
+// interface offers 3 different ways to append data, and a Flush() function.
+//
+// Example:
+//
+// string my_data;
+// ...
+// ByteSink* sink = ...
+// sink->Append(my_data.data(), my_data.size());
+// sink->Flush();
+//
+class LIBPROTOBUF_EXPORT ByteSink {
+ public:
+ ByteSink() {}
+ virtual ~ByteSink() {}
+
+ // Appends the "n" bytes starting at "bytes".
+ virtual void Append(const char* bytes, size_t n) = 0;
+
+ // Flushes internal buffers. The default implemenation does nothing. ByteSink
+ // subclasses may use internal buffers that require calling Flush() at the end
+ // of the stream.
+ virtual void Flush();
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSink);
+};
+
+// An abstract interface for an object that produces a fixed-size sequence of
+// bytes.
+//
+// Example:
+//
+// ByteSource* source = ...
+// while (source->Available() > 0) {
+// StringPiece data = source->Peek();
+// ... do something with "data" ...
+// source->Skip(data.length());
+// }
+//
+class LIBPROTOBUF_EXPORT ByteSource {
+ public:
+ ByteSource() {}
+ virtual ~ByteSource() {}
+
+ // Returns the number of bytes left to read from the source. Available()
+ // should decrease by N each time Skip(N) is called. Available() may not
+ // increase. Available() returning 0 indicates that the ByteSource is
+ // exhausted.
+ //
+ // Note: Size() may have been a more appropriate name as it's more
+ // indicative of the fixed-size nature of a ByteSource.
+ virtual size_t Available() const = 0;
+
+ // Returns a StringPiece of the next contiguous region of the source. Does not
+ // reposition the source. The returned region is empty iff Available() == 0.
+ //
+ // The returned region is valid until the next call to Skip() or until this
+ // object is destroyed, whichever occurs first.
+ //
+ // The length of the returned StringPiece will be <= Available().
+ virtual StringPiece Peek() = 0;
+
+ // Skips the next n bytes. Invalidates any StringPiece returned by a previous
+ // call to Peek().
+ //
+ // REQUIRES: Available() >= n
+ virtual void Skip(size_t n) = 0;
+
+ // Writes the next n bytes in this ByteSource to the given ByteSink, and
+ // advances this ByteSource past the copied bytes. The default implementation
+ // of this method just copies the bytes normally, but subclasses might
+ // override CopyTo to optimize certain cases.
+ //
+ // REQUIRES: Available() >= n
+ virtual void CopyTo(ByteSink* sink, size_t n);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSource);
+};
+
+//
+// Some commonly used implementations of ByteSink
+//
+
+// Implementation of ByteSink that writes to an unsized byte array. No
+// bounds-checking is performed--it is the caller's responsibility to ensure
+// that the destination array is large enough.
+//
+// Example:
+//
+// char buf[10];
+// UncheckedArrayByteSink sink(buf);
+// sink.Append("hi", 2); // OK
+// sink.Append(data, 100); // WOOPS! Overflows buf[10].
+//
+class LIBPROTOBUF_EXPORT UncheckedArrayByteSink : public ByteSink {
+ public:
+ explicit UncheckedArrayByteSink(char* dest) : dest_(dest) {}
+ virtual void Append(const char* data, size_t n);
+
+ // Returns the current output pointer so that a caller can see how many bytes
+ // were produced.
+ //
+ // Note: this method is not part of the ByteSink interface.
+ char* CurrentDestination() const { return dest_; }
+
+ private:
+ char* dest_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UncheckedArrayByteSink);
+};
+
+// Implementation of ByteSink that writes to a sized byte array. This sink will
+// not write more than "capacity" bytes to outbuf. Once "capacity" bytes are
+// appended, subsequent bytes will be ignored and Overflowed() will return true.
+// Overflowed() does not cause a runtime error (i.e., it does not CHECK fail).
+//
+// Example:
+//
+// char buf[10];
+// CheckedArrayByteSink sink(buf, 10);
+// sink.Append("hi", 2); // OK
+// sink.Append(data, 100); // Will only write 8 more bytes
+//
+class LIBPROTOBUF_EXPORT CheckedArrayByteSink : public ByteSink {
+ public:
+ CheckedArrayByteSink(char* outbuf, size_t capacity);
+ virtual void Append(const char* bytes, size_t n);
+
+ // Returns the number of bytes actually written to the sink.
+ size_t NumberOfBytesWritten() const { return size_; }
+
+ // Returns true if any bytes were discarded, i.e., if there was an
+ // attempt to write more than 'capacity' bytes.
+ bool Overflowed() const { return overflowed_; }
+
+ private:
+ char* outbuf_;
+ const size_t capacity_;
+ size_t size_;
+ bool overflowed_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CheckedArrayByteSink);
+};
+
+// Implementation of ByteSink that allocates an internal buffer (a char array)
+// and expands it as needed to accomodate appended data (similar to a string),
+// and allows the caller to take ownership of the internal buffer via the
+// GetBuffer() method. The buffer returned from GetBuffer() must be deleted by
+// the caller with delete[]. GetBuffer() also sets the internal buffer to be
+// empty, and subsequent appends to the sink will create a new buffer. The
+// destructor will free the internal buffer if GetBuffer() was not called.
+//
+// Example:
+//
+// GrowingArrayByteSink sink(10);
+// sink.Append("hi", 2);
+// sink.Append(data, n);
+// const char* buf = sink.GetBuffer(); // Ownership transferred
+// delete[] buf;
+//
+class LIBPROTOBUF_EXPORT GrowingArrayByteSink : public strings::ByteSink {
+ public:
+ explicit GrowingArrayByteSink(size_t estimated_size);
+ virtual ~GrowingArrayByteSink();
+ virtual void Append(const char* bytes, size_t n);
+
+ // Returns the allocated buffer, and sets nbytes to its size. The caller takes
+ // ownership of the buffer and must delete it with delete[].
+ char* GetBuffer(size_t* nbytes);
+
+ private:
+ void Expand(size_t amount);
+ void ShrinkToFit();
+
+ size_t capacity_;
+ char* buf_;
+ size_t size_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GrowingArrayByteSink);
+};
+
+// Implementation of ByteSink that appends to the given string.
+// Existing contents of "dest" are not modified; new data is appended.
+//
+// Example:
+//
+// string dest = "Hello ";
+// StringByteSink sink(&dest);
+// sink.Append("World", 5);
+// assert(dest == "Hello World");
+//
+class LIBPROTOBUF_EXPORT StringByteSink : public ByteSink {
+ public:
+ explicit StringByteSink(string* dest) : dest_(dest) {}
+ virtual void Append(const char* data, size_t n);
+
+ private:
+ string* dest_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringByteSink);
+};
+
+// Implementation of ByteSink that discards all data.
+//
+// Example:
+//
+// NullByteSink sink;
+// sink.Append(data, data.size()); // All data ignored.
+//
+class LIBPROTOBUF_EXPORT NullByteSink : public ByteSink {
+ public:
+ NullByteSink() {}
+ virtual void Append(const char *data, size_t n) {}
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NullByteSink);
+};
+
+//
+// Some commonly used implementations of ByteSource
+//
+
+// Implementation of ByteSource that reads from a StringPiece.
+//
+// Example:
+//
+// string data = "Hello";
+// ArrayByteSource source(data);
+// assert(source.Available() == 5);
+// assert(source.Peek() == "Hello");
+//
+class LIBPROTOBUF_EXPORT ArrayByteSource : public ByteSource {
+ public:
+ explicit ArrayByteSource(StringPiece s) : input_(s) {}
+
+ virtual size_t Available() const;
+ virtual StringPiece Peek();
+ virtual void Skip(size_t n);
+
+ private:
+ StringPiece input_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayByteSource);
+};
+
+// Implementation of ByteSource that wraps another ByteSource, limiting the
+// number of bytes returned.
+//
+// The caller maintains ownership of the underlying source, and may not use the
+// underlying source while using the LimitByteSource object. The underlying
+// source's pointer is advanced by n bytes every time this LimitByteSource
+// object is advanced by n.
+//
+// Example:
+//
+// string data = "Hello World";
+// ArrayByteSource abs(data);
+// assert(abs.Available() == data.size());
+//
+// LimitByteSource limit(abs, 5);
+// assert(limit.Available() == 5);
+// assert(limit.Peek() == "Hello");
+//
+class LIBPROTOBUF_EXPORT LimitByteSource : public ByteSource {
+ public:
+ // Returns at most "limit" bytes from "source".
+ LimitByteSource(ByteSource* source, size_t limit);
+
+ virtual size_t Available() const;
+ virtual StringPiece Peek();
+ virtual void Skip(size_t n);
+
+ // We override CopyTo so that we can forward to the underlying source, in
+ // case it has an efficient implementation of CopyTo.
+ virtual void CopyTo(ByteSink* sink, size_t n);
+
+ private:
+ ByteSource* source_;
+ size_t limit_;
+};
+
+} // namespace strings
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_
diff --git a/src/google/protobuf/stubs/bytestream_unittest.cc b/src/google/protobuf/stubs/bytestream_unittest.cc
new file mode 100644
index 00000000..06f114ab
--- /dev/null
+++ b/src/google/protobuf/stubs/bytestream_unittest.cc
@@ -0,0 +1,146 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/stubs/bytestream.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <algorithm>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace strings {
+namespace {
+
+// We use this class instead of ArrayByteSource to simulate a ByteSource that
+// contains multiple fragments. ArrayByteSource returns the entire array in
+// one fragment.
+class MockByteSource : public ByteSource {
+ public:
+ MockByteSource(StringPiece data, int block_size)
+ : data_(data), block_size_(block_size) {}
+
+ size_t Available() const { return data_.size(); }
+ StringPiece Peek() {
+ return data_.substr(0, block_size_);
+ }
+ void Skip(size_t n) { data_.remove_prefix(n); }
+
+ private:
+ StringPiece data_;
+ int block_size_;
+};
+
+TEST(ByteSourceTest, CopyTo) {
+ StringPiece data("Hello world!");
+ MockByteSource source(data, 3);
+ string str;
+ StringByteSink sink(&str);
+
+ source.CopyTo(&sink, data.size());
+ EXPECT_EQ(data, str);
+}
+
+TEST(ByteSourceTest, CopySubstringTo) {
+ StringPiece data("Hello world!");
+ MockByteSource source(data, 3);
+ source.Skip(1);
+ string str;
+ StringByteSink sink(&str);
+
+ source.CopyTo(&sink, data.size() - 2);
+ EXPECT_EQ(data.substr(1, data.size() - 2), str);
+ EXPECT_EQ("!", source.Peek());
+}
+
+TEST(ByteSourceTest, LimitByteSource) {
+ StringPiece data("Hello world!");
+ MockByteSource source(data, 3);
+ LimitByteSource limit_source(&source, 6);
+ EXPECT_EQ(6, limit_source.Available());
+ limit_source.Skip(1);
+ EXPECT_EQ(5, limit_source.Available());
+
+ {
+ string str;
+ StringByteSink sink(&str);
+ limit_source.CopyTo(&sink, limit_source.Available());
+ EXPECT_EQ("ello ", str);
+ EXPECT_EQ(0, limit_source.Available());
+ EXPECT_EQ(6, source.Available());
+ }
+
+ {
+ string str;
+ StringByteSink sink(&str);
+ source.CopyTo(&sink, source.Available());
+ EXPECT_EQ("world!", str);
+ EXPECT_EQ(0, source.Available());
+ }
+}
+
+TEST(ByteSourceTest, CopyToStringByteSink) {
+ StringPiece data("Hello world!");
+ MockByteSource source(data, 3);
+ string str;
+ StringByteSink sink(&str);
+ source.CopyTo(&sink, data.size());
+ EXPECT_EQ(data, str);
+}
+
+// Verify that ByteSink is subclassable and Flush() overridable.
+class FlushingByteSink : public StringByteSink {
+ public:
+ explicit FlushingByteSink(string* dest) : StringByteSink(dest) {}
+ virtual void Flush() { Append("z", 1); }
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FlushingByteSink);
+};
+
+// Write and Flush via the ByteSink superclass interface.
+void WriteAndFlush(ByteSink* s) {
+ s->Append("abc", 3);
+ s->Flush();
+}
+
+TEST(ByteSinkTest, Flush) {
+ string str;
+ FlushingByteSink f_sink(&str);
+ WriteAndFlush(&f_sink);
+ EXPECT_STREQ("abcz", str.c_str());
+}
+
+} // namespace
+} // namespace strings
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/callback.h b/src/google/protobuf/stubs/callback.h
new file mode 100644
index 00000000..c4f9edee
--- /dev/null
+++ b/src/google/protobuf/stubs/callback.h
@@ -0,0 +1,463 @@
+#ifndef GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
+#define GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
+
+#include <google/protobuf/stubs/macros.h>
+#include <google/protobuf/stubs/type_traits.h>
+
+// ===================================================================
+// emulates google3/base/callback.h
+
+namespace google {
+namespace protobuf {
+
+// Abstract interface for a callback. When calling an RPC, you must provide
+// a Closure to call when the procedure completes. See the Service interface
+// in service.h.
+//
+// To automatically construct a Closure which calls a particular function or
+// method with a particular set of parameters, use the NewCallback() function.
+// Example:
+// void FooDone(const FooResponse* response) {
+// ...
+// }
+//
+// void CallFoo() {
+// ...
+// // When done, call FooDone() and pass it a pointer to the response.
+// Closure* callback = NewCallback(&FooDone, response);
+// // Make the call.
+// service->Foo(controller, request, response, callback);
+// }
+//
+// Example that calls a method:
+// class Handler {
+// public:
+// ...
+//
+// void FooDone(const FooResponse* response) {
+// ...
+// }
+//
+// void CallFoo() {
+// ...
+// // When done, call FooDone() and pass it a pointer to the response.
+// Closure* callback = NewCallback(this, &Handler::FooDone, response);
+// // Make the call.
+// service->Foo(controller, request, response, callback);
+// }
+// };
+//
+// Currently NewCallback() supports binding zero, one, or two arguments.
+//
+// Callbacks created with NewCallback() automatically delete themselves when
+// executed. They should be used when a callback is to be called exactly
+// once (usually the case with RPC callbacks). If a callback may be called
+// a different number of times (including zero), create it with
+// NewPermanentCallback() instead. You are then responsible for deleting the
+// callback (using the "delete" keyword as normal).
+//
+// Note that NewCallback() is a bit touchy regarding argument types. Generally,
+// the values you provide for the parameter bindings must exactly match the
+// types accepted by the callback function. For example:
+// void Foo(string s);
+// NewCallback(&Foo, "foo"); // WON'T WORK: const char* != string
+// NewCallback(&Foo, string("foo")); // WORKS
+// Also note that the arguments cannot be references:
+// void Foo(const string& s);
+// string my_str;
+// NewCallback(&Foo, my_str); // WON'T WORK: Can't use referecnes.
+// However, correctly-typed pointers will work just fine.
+class LIBPROTOBUF_EXPORT Closure {
+ public:
+ Closure() {}
+ virtual ~Closure();
+
+ virtual void Run() = 0;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure);
+};
+
+template<typename R, typename A1>
+class LIBPROTOBUF_EXPORT ResultCallback1 {
+ public:
+ ResultCallback1() {}
+ virtual ~ResultCallback1() {}
+
+ virtual R Run(A1) = 0;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback1);
+};
+
+template<typename R, typename A1, typename A2>
+class LIBPROTOBUF_EXPORT ResultCallback2 {
+ public:
+ ResultCallback2() {}
+ virtual ~ResultCallback2() {}
+
+ virtual R Run(A1,A2) = 0;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback2);
+};
+
+namespace internal {
+
+class LIBPROTOBUF_EXPORT FunctionClosure0 : public Closure {
+ public:
+ typedef void (*FunctionType)();
+
+ FunctionClosure0(FunctionType function, bool self_deleting)
+ : function_(function), self_deleting_(self_deleting) {}
+ ~FunctionClosure0();
+
+ void Run() {
+ bool needs_delete = self_deleting_; // read in case callback deletes
+ function_();
+ if (needs_delete) delete this;
+ }
+
+ private:
+ FunctionType function_;
+ bool self_deleting_;
+};
+
+template <typename Class>
+class MethodClosure0 : public Closure {
+ public:
+ typedef void (Class::*MethodType)();
+
+ MethodClosure0(Class* object, MethodType method, bool self_deleting)
+ : object_(object), method_(method), self_deleting_(self_deleting) {}
+ ~MethodClosure0() {}
+
+ void Run() {
+ bool needs_delete = self_deleting_; // read in case callback deletes
+ (object_->*method_)();
+ if (needs_delete) delete this;
+ }
+
+ private:
+ Class* object_;
+ MethodType method_;
+ bool self_deleting_;
+};
+
+template <typename Arg1>
+class FunctionClosure1 : public Closure {
+ public:
+ typedef void (*FunctionType)(Arg1 arg1);
+
+ FunctionClosure1(FunctionType function, bool self_deleting,
+ Arg1 arg1)
+ : function_(function), self_deleting_(self_deleting),
+ arg1_(arg1) {}
+ ~FunctionClosure1() {}
+
+ void Run() {
+ bool needs_delete = self_deleting_; // read in case callback deletes
+ function_(arg1_);
+ if (needs_delete) delete this;
+ }
+
+ private:
+ FunctionType function_;
+ bool self_deleting_;
+ Arg1 arg1_;
+};
+
+template <typename Class, typename Arg1>
+class MethodClosure1 : public Closure {
+ public:
+ typedef void (Class::*MethodType)(Arg1 arg1);
+
+ MethodClosure1(Class* object, MethodType method, bool self_deleting,
+ Arg1 arg1)
+ : object_(object), method_(method), self_deleting_(self_deleting),
+ arg1_(arg1) {}
+ ~MethodClosure1() {}
+
+ void Run() {
+ bool needs_delete = self_deleting_; // read in case callback deletes
+ (object_->*method_)(arg1_);
+ if (needs_delete) delete this;
+ }
+
+ private:
+ Class* object_;
+ MethodType method_;
+ bool self_deleting_;
+ Arg1 arg1_;
+};
+
+template <typename Arg1, typename Arg2>
+class FunctionClosure2 : public Closure {
+ public:
+ typedef void (*FunctionType)(Arg1 arg1, Arg2 arg2);
+
+ FunctionClosure2(FunctionType function, bool self_deleting,
+ Arg1 arg1, Arg2 arg2)
+ : function_(function), self_deleting_(self_deleting),
+ arg1_(arg1), arg2_(arg2) {}
+ ~FunctionClosure2() {}
+
+ void Run() {
+ bool needs_delete = self_deleting_; // read in case callback deletes
+ function_(arg1_, arg2_);
+ if (needs_delete) delete this;
+ }
+
+ private:
+ FunctionType function_;
+ bool self_deleting_;
+ Arg1 arg1_;
+ Arg2 arg2_;
+};
+
+template <typename Class, typename Arg1, typename Arg2>
+class MethodClosure2 : public Closure {
+ public:
+ typedef void (Class::*MethodType)(Arg1 arg1, Arg2 arg2);
+
+ MethodClosure2(Class* object, MethodType method, bool self_deleting,
+ Arg1 arg1, Arg2 arg2)
+ : object_(object), method_(method), self_deleting_(self_deleting),
+ arg1_(arg1), arg2_(arg2) {}
+ ~MethodClosure2() {}
+
+ void Run() {
+ bool needs_delete = self_deleting_; // read in case callback deletes
+ (object_->*method_)(arg1_, arg2_);
+ if (needs_delete) delete this;
+ }
+
+ private:
+ Class* object_;
+ MethodType method_;
+ bool self_deleting_;
+ Arg1 arg1_;
+ Arg2 arg2_;
+};
+
+template<typename R, typename Arg1>
+class FunctionResultCallback_0_1 : public ResultCallback1<R, Arg1> {
+ public:
+ typedef R (*FunctionType)(Arg1 arg1);
+
+ FunctionResultCallback_0_1(FunctionType function, bool self_deleting)
+ : function_(function), self_deleting_(self_deleting) {}
+ ~FunctionResultCallback_0_1() {}
+
+ R Run(Arg1 a1) {
+ bool needs_delete = self_deleting_; // read in case callback deletes
+ R result = function_(a1);
+ if (needs_delete) delete this;
+ return result;
+ }
+
+ private:
+ FunctionType function_;
+ bool self_deleting_;
+};
+
+template<typename R, typename P1, typename A1>
+class FunctionResultCallback_1_1 : public ResultCallback1<R, A1> {
+ public:
+ typedef R (*FunctionType)(P1, A1);
+
+ FunctionResultCallback_1_1(FunctionType function, bool self_deleting,
+ P1 p1)
+ : function_(function), self_deleting_(self_deleting), p1_(p1) {}
+ ~FunctionResultCallback_1_1() {}
+
+ R Run(A1 a1) {
+ bool needs_delete = self_deleting_; // read in case callback deletes
+ R result = function_(p1_, a1);
+ if (needs_delete) delete this;
+ return result;
+ }
+
+ private:
+ FunctionType function_;
+ bool self_deleting_;
+ P1 p1_;
+};
+
+template <typename T>
+struct InternalConstRef {
+ typedef typename remove_reference<T>::type base_type;
+ typedef const base_type& type;
+};
+
+template <typename R, typename T, typename P1, typename P2, typename P3,
+ typename P4, typename P5, typename A1, typename A2>
+class MethodResultCallback_5_2 : public ResultCallback2<R, A1, A2> {
+ public:
+ typedef R (T::*MethodType)(P1, P2, P3, P4, P5, A1, A2);
+ MethodResultCallback_5_2(T* object, MethodType method, bool self_deleting,
+ P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
+ : object_(object),
+ method_(method),
+ self_deleting_(self_deleting),
+ p1_(p1),
+ p2_(p2),
+ p3_(p3),
+ p4_(p4),
+ p5_(p5) {}
+ ~MethodResultCallback_5_2() {}
+
+ R Run(A1 a1, A2 a2) {
+ bool needs_delete = self_deleting_;
+ R result = (object_->*method_)(p1_, p2_, p3_, p4_, p5_, a1, a2);
+ if (needs_delete) delete this;
+ return result;
+ }
+
+ private:
+ T* object_;
+ MethodType method_;
+ bool self_deleting_;
+ typename remove_reference<P1>::type p1_;
+ typename remove_reference<P2>::type p2_;
+ typename remove_reference<P3>::type p3_;
+ typename remove_reference<P4>::type p4_;
+ typename remove_reference<P5>::type p5_;
+};
+
+} // namespace internal
+
+// See Closure.
+inline Closure* NewCallback(void (*function)()) {
+ return new internal::FunctionClosure0(function, true);
+}
+
+// See Closure.
+inline Closure* NewPermanentCallback(void (*function)()) {
+ return new internal::FunctionClosure0(function, false);
+}
+
+// See Closure.
+template <typename Class>
+inline Closure* NewCallback(Class* object, void (Class::*method)()) {
+ return new internal::MethodClosure0<Class>(object, method, true);
+}
+
+// See Closure.
+template <typename Class>
+inline Closure* NewPermanentCallback(Class* object, void (Class::*method)()) {
+ return new internal::MethodClosure0<Class>(object, method, false);
+}
+
+// See Closure.
+template <typename Arg1>
+inline Closure* NewCallback(void (*function)(Arg1),
+ Arg1 arg1) {
+ return new internal::FunctionClosure1<Arg1>(function, true, arg1);
+}
+
+// See Closure.
+template <typename Arg1>
+inline Closure* NewPermanentCallback(void (*function)(Arg1),
+ Arg1 arg1) {
+ return new internal::FunctionClosure1<Arg1>(function, false, arg1);
+}
+
+// See Closure.
+template <typename Class, typename Arg1>
+inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1),
+ Arg1 arg1) {
+ return new internal::MethodClosure1<Class, Arg1>(object, method, true, arg1);
+}
+
+// See Closure.
+template <typename Class, typename Arg1>
+inline Closure* NewPermanentCallback(Class* object, void (Class::*method)(Arg1),
+ Arg1 arg1) {
+ return new internal::MethodClosure1<Class, Arg1>(object, method, false, arg1);
+}
+
+// See Closure.
+template <typename Arg1, typename Arg2>
+inline Closure* NewCallback(void (*function)(Arg1, Arg2),
+ Arg1 arg1, Arg2 arg2) {
+ return new internal::FunctionClosure2<Arg1, Arg2>(
+ function, true, arg1, arg2);
+}
+
+// See Closure.
+template <typename Arg1, typename Arg2>
+inline Closure* NewPermanentCallback(void (*function)(Arg1, Arg2),
+ Arg1 arg1, Arg2 arg2) {
+ return new internal::FunctionClosure2<Arg1, Arg2>(
+ function, false, arg1, arg2);
+}
+
+// See Closure.
+template <typename Class, typename Arg1, typename Arg2>
+inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1, Arg2),
+ Arg1 arg1, Arg2 arg2) {
+ return new internal::MethodClosure2<Class, Arg1, Arg2>(
+ object, method, true, arg1, arg2);
+}
+
+// See Closure.
+template <typename Class, typename Arg1, typename Arg2>
+inline Closure* NewPermanentCallback(
+ Class* object, void (Class::*method)(Arg1, Arg2),
+ Arg1 arg1, Arg2 arg2) {
+ return new internal::MethodClosure2<Class, Arg1, Arg2>(
+ object, method, false, arg1, arg2);
+}
+
+// See ResultCallback1
+template<typename R, typename A1>
+inline ResultCallback1<R, A1>* NewCallback(R (*function)(A1)) {
+ return new internal::FunctionResultCallback_0_1<R, A1>(function, true);
+}
+
+// See ResultCallback1
+template<typename R, typename A1>
+inline ResultCallback1<R, A1>* NewPermanentCallback(R (*function)(A1)) {
+ return new internal::FunctionResultCallback_0_1<R, A1>(function, false);
+}
+
+// See ResultCallback1
+template<typename R, typename P1, typename A1>
+inline ResultCallback1<R, A1>* NewCallback(R (*function)(P1, A1), P1 p1) {
+ return new internal::FunctionResultCallback_1_1<R, P1, A1>(
+ function, true, p1);
+}
+
+// See ResultCallback1
+template<typename R, typename P1, typename A1>
+inline ResultCallback1<R, A1>* NewPermanentCallback(
+ R (*function)(P1, A1), P1 p1) {
+ return new internal::FunctionResultCallback_1_1<R, P1, A1>(
+ function, false, p1);
+}
+
+// See MethodResultCallback_5_2
+template <typename R, typename T, typename P1, typename P2, typename P3,
+ typename P4, typename P5, typename A1, typename A2>
+inline ResultCallback2<R, A1, A2>* NewPermanentCallback(
+ T* object, R (T::*function)(P1, P2, P3, P4, P5, A1, A2),
+ typename internal::InternalConstRef<P1>::type p1,
+ typename internal::InternalConstRef<P2>::type p2,
+ typename internal::InternalConstRef<P3>::type p3,
+ typename internal::InternalConstRef<P4>::type p4,
+ typename internal::InternalConstRef<P5>::type p5) {
+ return new internal::MethodResultCallback_5_2<R, T, P1, P2, P3, P4, P5, A1,
+ A2>(object, function, false, p1,
+ p2, p3, p4, p5);
+}
+
+// A function which does nothing. Useful for creating no-op callbacks, e.g.:
+// Closure* nothing = NewCallback(&DoNothing);
+void LIBPROTOBUF_EXPORT DoNothing();
+
+
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
diff --git a/src/google/protobuf/stubs/casts.h b/src/google/protobuf/stubs/casts.h
index cccf65a1..be652849 100644
--- a/src/google/protobuf/stubs/casts.h
+++ b/src/google/protobuf/stubs/casts.h
@@ -111,12 +111,22 @@ inline To down_cast(From& f) {
return *static_cast<ToAsPointer>(&f);
}
+template<typename To, typename From>
+inline To bit_cast(const From& from) {
+ GOOGLE_COMPILE_ASSERT(sizeof(From) == sizeof(To),
+ bit_cast_with_different_sizes);
+ To dest;
+ memcpy(&dest, &from, sizeof(dest));
+ return dest;
+}
+
} // namespace internal
// We made these internal so that they would show up as such in the docs,
// but we don't want to stick "internal::" in front of them everywhere.
using internal::implicit_cast;
using internal::down_cast;
+using internal::bit_cast;
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc
index 54e00ccb..d470fc72 100644
--- a/src/google/protobuf/stubs/common.cc
+++ b/src/google/protobuf/stubs/common.cc
@@ -32,12 +32,13 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/strutil.h>
#include <stdio.h>
#include <errno.h>
#include <vector>
-#include "config.h"
-
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN // We only need minimal includes
#include <windows.h>
@@ -148,6 +149,27 @@ LogMessage& LogMessage::operator<<(const char* value) {
return *this;
}
+LogMessage& LogMessage::operator<<(const StringPiece& value) {
+ message_ += value.ToString();
+ return *this;
+}
+
+LogMessage& LogMessage::operator<<(long long value) {
+ message_ += SimpleItoa(value);
+ return *this;
+}
+
+LogMessage& LogMessage::operator<<(unsigned long long value) {
+ message_ += SimpleItoa(value);
+ return *this;
+}
+
+LogMessage& LogMessage::operator<<(
+ const ::google::protobuf::util::Status& status) {
+ message_ += status.ToString();
+ return *this;
+}
+
// Since this is just for logging, we don't care if the current locale changes
// the results -- in fact, we probably prefer that. So we use snprintf()
// instead of Simple*toa().
@@ -167,7 +189,7 @@ LogMessage& LogMessage::operator<<(const char* value) {
DECLARE_STREAM_OPERATOR(char , "%c" )
DECLARE_STREAM_OPERATOR(int , "%d" )
-DECLARE_STREAM_OPERATOR(uint , "%u" )
+DECLARE_STREAM_OPERATOR(unsigned int , "%u" )
DECLARE_STREAM_OPERATOR(long , "%ld")
DECLARE_STREAM_OPERATOR(unsigned long, "%lu")
DECLARE_STREAM_OPERATOR(double , "%g" )
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index c3f735a2..de866e14 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -35,18 +35,16 @@
#ifndef GOOGLE_PROTOBUF_COMMON_H__
#define GOOGLE_PROTOBUF_COMMON_H__
-#include <assert.h>
-#include <stdlib.h>
-#include <cstddef>
-#include <string>
-#include <string.h>
-#if defined(__osf__)
-// Tru64 lacks stdint.h, but has inttypes.h which defines a superset of
-// what stdint.h would define.
-#include <inttypes.h>
-#elif !defined(_MSC_VER)
-#include <stdint.h>
-#endif
+
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/macros.h>
+#include <google/protobuf/stubs/platform_macros.h>
+
+// TODO(liujisi): Remove the following includes after the include clean-up.
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
+#include <google/protobuf/stubs/mutex.h>
+#include <google/protobuf/stubs/callback.h>
#ifndef PROTOBUF_USE_EXCEPTIONS
#if defined(_MSC_VER) && defined(_CPPUNWIND)
@@ -61,6 +59,13 @@
#if PROTOBUF_USE_EXCEPTIONS
#include <exception>
#endif
+#if defined(__APPLE__)
+#include <TargetConditionals.h> // for TARGET_OS_IPHONE
+#endif
+
+#if defined(__ANDROID__) || defined(GOOGLE_PROTOBUF_OS_ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
+#include <pthread.h>
+#endif
#if defined(_WIN32) && defined(GetMessage)
// Allow GetMessage to be used as a valid method name in protobuf classes.
@@ -79,33 +84,10 @@ inline BOOL GetMessage(
}
#endif
-
namespace std {}
namespace google {
namespace protobuf {
-
-#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
-#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
- TypeName(const TypeName&); \
- void operator=(const TypeName&)
-
-#if defined(_MSC_VER) && defined(PROTOBUF_USE_DLLS)
- #ifdef LIBPROTOBUF_EXPORTS
- #define LIBPROTOBUF_EXPORT __declspec(dllexport)
- #else
- #define LIBPROTOBUF_EXPORT __declspec(dllimport)
- #endif
- #ifdef LIBPROTOC_EXPORTS
- #define LIBPROTOC_EXPORT __declspec(dllexport)
- #else
- #define LIBPROTOC_EXPORT __declspec(dllimport)
- #endif
-#else
- #define LIBPROTOBUF_EXPORT
- #define LIBPROTOC_EXPORT
-#endif
-
namespace internal {
// Some of these constants are macros rather than const ints so that they can
@@ -151,1022 +133,6 @@ std::string LIBPROTOBUF_EXPORT VersionString(int version);
GOOGLE_PROTOBUF_VERSION, GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION, \
__FILE__)
-// ===================================================================
-// from google3/base/port.h
-
-typedef unsigned int uint;
-
-#ifdef _MSC_VER
-typedef __int8 int8;
-typedef __int16 int16;
-typedef __int32 int32;
-typedef __int64 int64;
-
-typedef unsigned __int8 uint8;
-typedef unsigned __int16 uint16;
-typedef unsigned __int32 uint32;
-typedef unsigned __int64 uint64;
-#else
-typedef int8_t int8;
-typedef int16_t int16;
-typedef int32_t int32;
-typedef int64_t int64;
-
-typedef uint8_t uint8;
-typedef uint16_t uint16;
-typedef uint32_t uint32;
-typedef uint64_t uint64;
-#endif
-
-// long long macros to be used because gcc and vc++ use different suffixes,
-// and different size specifiers in format strings
-#undef GOOGLE_LONGLONG
-#undef GOOGLE_ULONGLONG
-#undef GOOGLE_LL_FORMAT
-
-#ifdef _MSC_VER
-#define GOOGLE_LONGLONG(x) x##I64
-#define GOOGLE_ULONGLONG(x) x##UI64
-#define GOOGLE_LL_FORMAT "I64" // As in printf("%I64d", ...)
-#else
-#define GOOGLE_LONGLONG(x) x##LL
-#define GOOGLE_ULONGLONG(x) x##ULL
-#define GOOGLE_LL_FORMAT "ll" // As in "%lld". Note that "q" is poor form also.
-#endif
-
-static const int32 kint32max = 0x7FFFFFFF;
-static const int32 kint32min = -kint32max - 1;
-static const int64 kint64max = GOOGLE_LONGLONG(0x7FFFFFFFFFFFFFFF);
-static const int64 kint64min = -kint64max - 1;
-static const uint32 kuint32max = 0xFFFFFFFFu;
-static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF);
-
-// -------------------------------------------------------------------
-// Annotations: Some parts of the code have been annotated in ways that might
-// be useful to some compilers or tools, but are not supported universally.
-// You can #define these annotations yourself if the default implementation
-// is not right for you.
-
-#ifndef GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
-// For functions we want to force inline.
-// Introduced in gcc 3.1.
-#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline))
-#else
-// Other compilers will have to figure it out for themselves.
-#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-#endif
-#endif
-
-#ifndef GOOGLE_ATTRIBUTE_NOINLINE
-#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
-// For functions we want to force not inline.
-// Introduced in gcc 3.1.
-#define GOOGLE_ATTRIBUTE_NOINLINE __attribute__ ((noinline))
-#else
-// Other compilers will have to figure it out for themselves.
-#define GOOGLE_ATTRIBUTE_NOINLINE
-#endif
-#endif
-
-#ifndef GOOGLE_ATTRIBUTE_DEPRECATED
-#ifdef __GNUC__
-// If the method/variable/type is used anywhere, produce a warning.
-#define GOOGLE_ATTRIBUTE_DEPRECATED __attribute__((deprecated))
-#else
-#define GOOGLE_ATTRIBUTE_DEPRECATED
-#endif
-#endif
-
-#ifndef GOOGLE_PREDICT_TRUE
-#ifdef __GNUC__
-// Provided at least since GCC 3.0.
-#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
-#else
-#define GOOGLE_PREDICT_TRUE
-#endif
-#endif
-
-#ifndef GOOGLE_PREDICT_FALSE
-#ifdef __GNUC__
-// Provided at least since GCC 3.0.
-#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(!!(x), 1))
-#else
-#define GOOGLE_PREDICT_FALSE
-#endif
-#endif
-
-// Delimits a block of code which may write to memory which is simultaneously
-// written by other threads, but which has been determined to be thread-safe
-// (e.g. because it is an idempotent write).
-#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN
-#define GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN()
-#endif
-#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_END
-#define GOOGLE_SAFE_CONCURRENT_WRITES_END()
-#endif
-
-#define GOOGLE_GUARDED_BY(x)
-#define GOOGLE_FALLTHROUGH_INTENDED
-#define GOOGLE_ATTRIBUTE_COLD
-
-// x86 and x86-64 can perform unaligned loads/stores directly.
-#if defined(_M_X64) || defined(__x86_64__) || \
- defined(_M_IX86) || defined(__i386__)
-
-#define GOOGLE_UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
-#define GOOGLE_UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
-#define GOOGLE_UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64 *>(_p))
-
-#define GOOGLE_UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
-#define GOOGLE_UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
-#define GOOGLE_UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64 *>(_p) = (_val))
-
-#else
-inline uint16 GOOGLE_UNALIGNED_LOAD16(const void *p) {
- uint16 t;
- memcpy(&t, p, sizeof t);
- return t;
-}
-
-inline uint32 GOOGLE_UNALIGNED_LOAD32(const void *p) {
- uint32 t;
- memcpy(&t, p, sizeof t);
- return t;
-}
-
-inline uint64 GOOGLE_UNALIGNED_LOAD64(const void *p) {
- uint64 t;
- memcpy(&t, p, sizeof t);
- return t;
-}
-
-inline void GOOGLE_UNALIGNED_STORE16(void *p, uint16 v) {
- memcpy(p, &v, sizeof v);
-}
-
-inline void GOOGLE_UNALIGNED_STORE32(void *p, uint32 v) {
- memcpy(p, &v, sizeof v);
-}
-
-inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) {
- memcpy(p, &v, sizeof v);
-}
-#endif
-
-#if defined(_MSC_VER)
-#define GOOGLE_THREAD_LOCAL __declspec(thread)
-#else
-#define GOOGLE_THREAD_LOCAL __thread
-#endif
-
-// ===================================================================
-// from google3/base/basictypes.h
-
-// The GOOGLE_ARRAYSIZE(arr) macro returns the # of elements in an array arr.
-// The expression is a compile-time constant, and therefore can be
-// used in defining new arrays, for example.
-//
-// GOOGLE_ARRAYSIZE catches a few type errors. If you see a compiler error
-//
-// "warning: division by zero in ..."
-//
-// when using GOOGLE_ARRAYSIZE, you are (wrongfully) giving it a pointer.
-// You should only use GOOGLE_ARRAYSIZE on statically allocated arrays.
-//
-// The following comments are on the implementation details, and can
-// be ignored by the users.
-//
-// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in
-// the array) and sizeof(*(arr)) (the # of bytes in one array
-// element). If the former is divisible by the latter, perhaps arr is
-// indeed an array, in which case the division result is the # of
-// elements in the array. Otherwise, arr cannot possibly be an array,
-// and we generate a compiler error to prevent the code from
-// compiling.
-//
-// Since the size of bool is implementation-defined, we need to cast
-// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
-// result has type size_t.
-//
-// This macro is not perfect as it wrongfully accepts certain
-// pointers, namely where the pointer size is divisible by the pointee
-// size. Since all our code has to go through a 32-bit compiler,
-// where a pointer is 4 bytes, this means all pointers to a type whose
-// size is 3 or greater than 4 will be (righteously) rejected.
-//
-// Kudos to Jorg Brown for this simple and elegant implementation.
-
-#undef GOOGLE_ARRAYSIZE
-#define GOOGLE_ARRAYSIZE(a) \
- ((sizeof(a) / sizeof(*(a))) / \
- static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
-
-// The COMPILE_ASSERT macro can be used to verify that a compile time
-// expression is true. For example, you could use it to verify the
-// size of a static array:
-//
-// COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
-// content_type_names_incorrect_size);
-//
-// or to make sure a struct is smaller than a certain size:
-//
-// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
-//
-// The second argument to the macro is the name of the variable. If
-// the expression is false, most compilers will issue a warning/error
-// containing the name of the variable.
-
-namespace internal {
-
-template <bool>
-struct CompileAssert {
-};
-
-} // namespace internal
-
-#undef GOOGLE_COMPILE_ASSERT
-#define GOOGLE_COMPILE_ASSERT(expr, msg) \
- ::google::protobuf::internal::CompileAssert<(bool(expr))> \
- msg[bool(expr) ? 1 : -1]; \
- (void)msg
-
-
-// Implementation details of COMPILE_ASSERT:
-//
-// - COMPILE_ASSERT works by defining an array type that has -1
-// elements (and thus is invalid) when the expression is false.
-//
-// - The simpler definition
-//
-// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
-//
-// does not work, as gcc supports variable-length arrays whose sizes
-// are determined at run-time (this is gcc's extension and not part
-// of the C++ standard). As a result, gcc fails to reject the
-// following code with the simple definition:
-//
-// int foo;
-// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
-// // not a compile-time constant.
-//
-// - By using the type CompileAssert<(bool(expr))>, we ensures that
-// expr is a compile-time constant. (Template arguments must be
-// determined at compile-time.)
-//
-// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
-// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
-//
-// CompileAssert<bool(expr)>
-//
-// instead, these compilers will refuse to compile
-//
-// COMPILE_ASSERT(5 > 0, some_message);
-//
-// (They seem to think the ">" in "5 > 0" marks the end of the
-// template argument list.)
-//
-// - The array size is (bool(expr) ? 1 : -1), instead of simply
-//
-// ((expr) ? 1 : -1).
-//
-// This is to avoid running into a bug in MS VC 7.1, which
-// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
-
-// ===================================================================
-// from google3/base/scoped_ptr.h
-
-namespace internal {
-
-// This is an implementation designed to match the anticipated future TR2
-// implementation of the scoped_ptr class, and its closely-related brethren,
-// scoped_array, scoped_ptr_malloc, and make_scoped_ptr.
-
-template <class C> class scoped_ptr;
-template <class C> class scoped_array;
-
-// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
-// automatically deletes the pointer it holds (if any).
-// That is, scoped_ptr<T> owns the T object that it points to.
-// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
-//
-// The size of a scoped_ptr is small:
-// sizeof(scoped_ptr<C>) == sizeof(C*)
-template <class C>
-class scoped_ptr {
- public:
-
- // The element type
- typedef C element_type;
-
- // Constructor. Defaults to initializing with NULL.
- // There is no way to create an uninitialized scoped_ptr.
- // The input parameter must be allocated with new.
- explicit scoped_ptr(C* p = NULL) : ptr_(p) { }
-
- // Destructor. If there is a C object, delete it.
- // We don't need to test ptr_ == NULL because C++ does that for us.
- ~scoped_ptr() {
- enum { type_must_be_complete = sizeof(C) };
- delete ptr_;
- }
-
- // Reset. Deletes the current owned object, if any.
- // Then takes ownership of a new object, if given.
- // this->reset(this->get()) works.
- void reset(C* p = NULL) {
- if (p != ptr_) {
- enum { type_must_be_complete = sizeof(C) };
- delete ptr_;
- ptr_ = p;
- }
- }
-
- // Accessors to get the owned object.
- // operator* and operator-> will assert() if there is no current object.
- C& operator*() const {
- assert(ptr_ != NULL);
- return *ptr_;
- }
- C* operator->() const {
- assert(ptr_ != NULL);
- return ptr_;
- }
- C* get() const { return ptr_; }
-
- // Comparison operators.
- // These return whether two scoped_ptr refer to the same object, not just to
- // two different but equal objects.
- bool operator==(C* p) const { return ptr_ == p; }
- bool operator!=(C* p) const { return ptr_ != p; }
-
- // Swap two scoped pointers.
- void swap(scoped_ptr& p2) {
- C* tmp = ptr_;
- ptr_ = p2.ptr_;
- p2.ptr_ = tmp;
- }
-
- // Release a pointer.
- // The return value is the current pointer held by this object.
- // If this object holds a NULL pointer, the return value is NULL.
- // After this operation, this object will hold a NULL pointer,
- // and will not own the object any more.
- C* release() {
- C* retVal = ptr_;
- ptr_ = NULL;
- return retVal;
- }
-
- private:
- C* ptr_;
-
- // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't
- // make sense, and if C2 == C, it still doesn't make sense because you should
- // never have the same object owned by two different scoped_ptrs.
- template <class C2> bool operator==(scoped_ptr<C2> const& p2) const;
- template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const;
-
- // Disallow evil constructors
- scoped_ptr(const scoped_ptr&);
- void operator=(const scoped_ptr&);
-};
-
-// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
-// with new [] and the destructor deletes objects with delete [].
-//
-// As with scoped_ptr<C>, a scoped_array<C> either points to an object
-// or is NULL. A scoped_array<C> owns the object that it points to.
-//
-// Size: sizeof(scoped_array<C>) == sizeof(C*)
-template <class C>
-class scoped_array {
- public:
-
- // The element type
- typedef C element_type;
-
- // Constructor. Defaults to initializing with NULL.
- // There is no way to create an uninitialized scoped_array.
- // The input parameter must be allocated with new [].
- explicit scoped_array(C* p = NULL) : array_(p) { }
-
- // Destructor. If there is a C object, delete it.
- // We don't need to test ptr_ == NULL because C++ does that for us.
- ~scoped_array() {
- enum { type_must_be_complete = sizeof(C) };
- delete[] array_;
- }
-
- // Reset. Deletes the current owned object, if any.
- // Then takes ownership of a new object, if given.
- // this->reset(this->get()) works.
- void reset(C* p = NULL) {
- if (p != array_) {
- enum { type_must_be_complete = sizeof(C) };
- delete[] array_;
- array_ = p;
- }
- }
-
- // Get one element of the current object.
- // Will assert() if there is no current object, or index i is negative.
- C& operator[](std::ptrdiff_t i) const {
- assert(i >= 0);
- assert(array_ != NULL);
- return array_[i];
- }
-
- // Get a pointer to the zeroth element of the current object.
- // If there is no current object, return NULL.
- C* get() const {
- return array_;
- }
-
- // Comparison operators.
- // These return whether two scoped_array refer to the same object, not just to
- // two different but equal objects.
- bool operator==(C* p) const { return array_ == p; }
- bool operator!=(C* p) const { return array_ != p; }
-
- // Swap two scoped arrays.
- void swap(scoped_array& p2) {
- C* tmp = array_;
- array_ = p2.array_;
- p2.array_ = tmp;
- }
-
- // Release an array.
- // The return value is the current pointer held by this object.
- // If this object holds a NULL pointer, the return value is NULL.
- // After this operation, this object will hold a NULL pointer,
- // and will not own the object any more.
- C* release() {
- C* retVal = array_;
- array_ = NULL;
- return retVal;
- }
-
- private:
- C* array_;
-
- // Forbid comparison of different scoped_array types.
- template <class C2> bool operator==(scoped_array<C2> const& p2) const;
- template <class C2> bool operator!=(scoped_array<C2> const& p2) const;
-
- // Disallow evil constructors
- scoped_array(const scoped_array&);
- void operator=(const scoped_array&);
-};
-
-} // namespace internal
-
-// We made these internal so that they would show up as such in the docs,
-// but we don't want to stick "internal::" in front of them everywhere.
-using internal::scoped_ptr;
-using internal::scoped_array;
-
-// ===================================================================
-// emulates google3/base/logging.h
-
-enum LogLevel {
- LOGLEVEL_INFO, // Informational. This is never actually used by
- // libprotobuf.
- LOGLEVEL_WARNING, // Warns about issues that, although not technically a
- // problem now, could cause problems in the future. For
- // example, a // warning will be printed when parsing a
- // message that is near the message size limit.
- LOGLEVEL_ERROR, // An error occurred which should never happen during
- // normal use.
- LOGLEVEL_FATAL, // An error occurred from which the library cannot
- // recover. This usually indicates a programming error
- // in the code which calls the library, especially when
- // compiled in debug mode.
-
-#ifdef NDEBUG
- LOGLEVEL_DFATAL = LOGLEVEL_ERROR
-#else
- LOGLEVEL_DFATAL = LOGLEVEL_FATAL
-#endif
-};
-
-namespace internal {
-
-class LogFinisher;
-
-class LIBPROTOBUF_EXPORT LogMessage {
- public:
- LogMessage(LogLevel level, const char* filename, int line);
- ~LogMessage();
-
- LogMessage& operator<<(const std::string& value);
- LogMessage& operator<<(const char* value);
- LogMessage& operator<<(char value);
- LogMessage& operator<<(int value);
- LogMessage& operator<<(uint value);
- LogMessage& operator<<(long value);
- LogMessage& operator<<(unsigned long value);
- LogMessage& operator<<(double value);
- LogMessage& operator<<(void* value);
-
- private:
- friend class LogFinisher;
- void Finish();
-
- LogLevel level_;
- const char* filename_;
- int line_;
- std::string message_;
-};
-
-// Used to make the entire "LOG(BLAH) << etc." expression have a void return
-// type and print a newline after each message.
-class LIBPROTOBUF_EXPORT LogFinisher {
- public:
- void operator=(LogMessage& other);
-};
-
-} // namespace internal
-
-// Undef everything in case we're being mixed with some other Google library
-// which already defined them itself. Presumably all Google libraries will
-// support the same syntax for these so it should not be a big deal if they
-// end up using our definitions instead.
-#undef GOOGLE_LOG
-#undef GOOGLE_LOG_IF
-
-#undef GOOGLE_CHECK
-#undef GOOGLE_CHECK_OK
-#undef GOOGLE_CHECK_EQ
-#undef GOOGLE_CHECK_NE
-#undef GOOGLE_CHECK_LT
-#undef GOOGLE_CHECK_LE
-#undef GOOGLE_CHECK_GT
-#undef GOOGLE_CHECK_GE
-#undef GOOGLE_CHECK_NOTNULL
-
-#undef GOOGLE_DLOG
-#undef GOOGLE_DCHECK
-#undef GOOGLE_DCHECK_EQ
-#undef GOOGLE_DCHECK_NE
-#undef GOOGLE_DCHECK_LT
-#undef GOOGLE_DCHECK_LE
-#undef GOOGLE_DCHECK_GT
-#undef GOOGLE_DCHECK_GE
-
-#define GOOGLE_LOG(LEVEL) \
- ::google::protobuf::internal::LogFinisher() = \
- ::google::protobuf::internal::LogMessage( \
- ::google::protobuf::LOGLEVEL_##LEVEL, __FILE__, __LINE__)
-#define GOOGLE_LOG_IF(LEVEL, CONDITION) \
- !(CONDITION) ? (void)0 : GOOGLE_LOG(LEVEL)
-
-#define GOOGLE_CHECK(EXPRESSION) \
- GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": "
-#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(A)
-#define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B))
-#define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B))
-#define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B))
-#define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK((A) <= (B))
-#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) > (B))
-#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B))
-
-namespace internal {
-template<typename T>
-T* CheckNotNull(const char* /* file */, int /* line */,
- const char* name, T* val) {
- if (val == NULL) {
- GOOGLE_LOG(FATAL) << name;
- }
- return val;
-}
-} // namespace internal
-#define GOOGLE_CHECK_NOTNULL(A) \
- ::google::protobuf::internal::CheckNotNull(\
- __FILE__, __LINE__, "'" #A "' must not be NULL", (A))
-
-#ifdef NDEBUG
-
-#define GOOGLE_DLOG GOOGLE_LOG_IF(INFO, false)
-
-#define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION)
-#define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK((A) == (B))
-#define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK((A) != (B))
-#define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK((A) < (B))
-#define GOOGLE_DCHECK_LE(A, B) GOOGLE_DCHECK((A) <= (B))
-#define GOOGLE_DCHECK_GT(A, B) GOOGLE_DCHECK((A) > (B))
-#define GOOGLE_DCHECK_GE(A, B) GOOGLE_DCHECK((A) >= (B))
-
-#else // NDEBUG
-
-#define GOOGLE_DLOG GOOGLE_LOG
-
-#define GOOGLE_DCHECK GOOGLE_CHECK
-#define GOOGLE_DCHECK_EQ GOOGLE_CHECK_EQ
-#define GOOGLE_DCHECK_NE GOOGLE_CHECK_NE
-#define GOOGLE_DCHECK_LT GOOGLE_CHECK_LT
-#define GOOGLE_DCHECK_LE GOOGLE_CHECK_LE
-#define GOOGLE_DCHECK_GT GOOGLE_CHECK_GT
-#define GOOGLE_DCHECK_GE GOOGLE_CHECK_GE
-
-#endif // !NDEBUG
-
-typedef void LogHandler(LogLevel level, const char* filename, int line,
- const std::string& message);
-
-// The protobuf library sometimes writes warning and error messages to
-// stderr. These messages are primarily useful for developers, but may
-// also help end users figure out a problem. If you would prefer that
-// these messages be sent somewhere other than stderr, call SetLogHandler()
-// to set your own handler. This returns the old handler. Set the handler
-// to NULL to ignore log messages (but see also LogSilencer, below).
-//
-// Obviously, SetLogHandler is not thread-safe. You should only call it
-// at initialization time, and probably not from library code. If you
-// simply want to suppress log messages temporarily (e.g. because you
-// have some code that tends to trigger them frequently and you know
-// the warnings are not important to you), use the LogSilencer class
-// below.
-LIBPROTOBUF_EXPORT LogHandler* SetLogHandler(LogHandler* new_func);
-
-// Create a LogSilencer if you want to temporarily suppress all log
-// messages. As long as any LogSilencer objects exist, non-fatal
-// log messages will be discarded (the current LogHandler will *not*
-// be called). Constructing a LogSilencer is thread-safe. You may
-// accidentally suppress log messages occurring in another thread, but
-// since messages are generally for debugging purposes only, this isn't
-// a big deal. If you want to intercept log messages, use SetLogHandler().
-class LIBPROTOBUF_EXPORT LogSilencer {
- public:
- LogSilencer();
- ~LogSilencer();
-};
-
-// ===================================================================
-// emulates google3/base/callback.h
-
-// Abstract interface for a callback. When calling an RPC, you must provide
-// a Closure to call when the procedure completes. See the Service interface
-// in service.h.
-//
-// To automatically construct a Closure which calls a particular function or
-// method with a particular set of parameters, use the NewCallback() function.
-// Example:
-// void FooDone(const FooResponse* response) {
-// ...
-// }
-//
-// void CallFoo() {
-// ...
-// // When done, call FooDone() and pass it a pointer to the response.
-// Closure* callback = NewCallback(&FooDone, response);
-// // Make the call.
-// service->Foo(controller, request, response, callback);
-// }
-//
-// Example that calls a method:
-// class Handler {
-// public:
-// ...
-//
-// void FooDone(const FooResponse* response) {
-// ...
-// }
-//
-// void CallFoo() {
-// ...
-// // When done, call FooDone() and pass it a pointer to the response.
-// Closure* callback = NewCallback(this, &Handler::FooDone, response);
-// // Make the call.
-// service->Foo(controller, request, response, callback);
-// }
-// };
-//
-// Currently NewCallback() supports binding zero, one, or two arguments.
-//
-// Callbacks created with NewCallback() automatically delete themselves when
-// executed. They should be used when a callback is to be called exactly
-// once (usually the case with RPC callbacks). If a callback may be called
-// a different number of times (including zero), create it with
-// NewPermanentCallback() instead. You are then responsible for deleting the
-// callback (using the "delete" keyword as normal).
-//
-// Note that NewCallback() is a bit touchy regarding argument types. Generally,
-// the values you provide for the parameter bindings must exactly match the
-// types accepted by the callback function. For example:
-// void Foo(string s);
-// NewCallback(&Foo, "foo"); // WON'T WORK: const char* != string
-// NewCallback(&Foo, string("foo")); // WORKS
-// Also note that the arguments cannot be references:
-// void Foo(const string& s);
-// string my_str;
-// NewCallback(&Foo, my_str); // WON'T WORK: Can't use referecnes.
-// However, correctly-typed pointers will work just fine.
-class LIBPROTOBUF_EXPORT Closure {
- public:
- Closure() {}
- virtual ~Closure();
-
- virtual void Run() = 0;
-
- private:
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure);
-};
-
-namespace internal {
-
-class LIBPROTOBUF_EXPORT FunctionClosure0 : public Closure {
- public:
- typedef void (*FunctionType)();
-
- FunctionClosure0(FunctionType function, bool self_deleting)
- : function_(function), self_deleting_(self_deleting) {}
- ~FunctionClosure0();
-
- void Run() {
- bool needs_delete = self_deleting_; // read in case callback deletes
- function_();
- if (needs_delete) delete this;
- }
-
- private:
- FunctionType function_;
- bool self_deleting_;
-};
-
-template <typename Class>
-class MethodClosure0 : public Closure {
- public:
- typedef void (Class::*MethodType)();
-
- MethodClosure0(Class* object, MethodType method, bool self_deleting)
- : object_(object), method_(method), self_deleting_(self_deleting) {}
- ~MethodClosure0() {}
-
- void Run() {
- bool needs_delete = self_deleting_; // read in case callback deletes
- (object_->*method_)();
- if (needs_delete) delete this;
- }
-
- private:
- Class* object_;
- MethodType method_;
- bool self_deleting_;
-};
-
-template <typename Arg1>
-class FunctionClosure1 : public Closure {
- public:
- typedef void (*FunctionType)(Arg1 arg1);
-
- FunctionClosure1(FunctionType function, bool self_deleting,
- Arg1 arg1)
- : function_(function), self_deleting_(self_deleting),
- arg1_(arg1) {}
- ~FunctionClosure1() {}
-
- void Run() {
- bool needs_delete = self_deleting_; // read in case callback deletes
- function_(arg1_);
- if (needs_delete) delete this;
- }
-
- private:
- FunctionType function_;
- bool self_deleting_;
- Arg1 arg1_;
-};
-
-template <typename Class, typename Arg1>
-class MethodClosure1 : public Closure {
- public:
- typedef void (Class::*MethodType)(Arg1 arg1);
-
- MethodClosure1(Class* object, MethodType method, bool self_deleting,
- Arg1 arg1)
- : object_(object), method_(method), self_deleting_(self_deleting),
- arg1_(arg1) {}
- ~MethodClosure1() {}
-
- void Run() {
- bool needs_delete = self_deleting_; // read in case callback deletes
- (object_->*method_)(arg1_);
- if (needs_delete) delete this;
- }
-
- private:
- Class* object_;
- MethodType method_;
- bool self_deleting_;
- Arg1 arg1_;
-};
-
-template <typename Arg1, typename Arg2>
-class FunctionClosure2 : public Closure {
- public:
- typedef void (*FunctionType)(Arg1 arg1, Arg2 arg2);
-
- FunctionClosure2(FunctionType function, bool self_deleting,
- Arg1 arg1, Arg2 arg2)
- : function_(function), self_deleting_(self_deleting),
- arg1_(arg1), arg2_(arg2) {}
- ~FunctionClosure2() {}
-
- void Run() {
- bool needs_delete = self_deleting_; // read in case callback deletes
- function_(arg1_, arg2_);
- if (needs_delete) delete this;
- }
-
- private:
- FunctionType function_;
- bool self_deleting_;
- Arg1 arg1_;
- Arg2 arg2_;
-};
-
-template <typename Class, typename Arg1, typename Arg2>
-class MethodClosure2 : public Closure {
- public:
- typedef void (Class::*MethodType)(Arg1 arg1, Arg2 arg2);
-
- MethodClosure2(Class* object, MethodType method, bool self_deleting,
- Arg1 arg1, Arg2 arg2)
- : object_(object), method_(method), self_deleting_(self_deleting),
- arg1_(arg1), arg2_(arg2) {}
- ~MethodClosure2() {}
-
- void Run() {
- bool needs_delete = self_deleting_; // read in case callback deletes
- (object_->*method_)(arg1_, arg2_);
- if (needs_delete) delete this;
- }
-
- private:
- Class* object_;
- MethodType method_;
- bool self_deleting_;
- Arg1 arg1_;
- Arg2 arg2_;
-};
-
-} // namespace internal
-
-// See Closure.
-inline Closure* NewCallback(void (*function)()) {
- return new internal::FunctionClosure0(function, true);
-}
-
-// See Closure.
-inline Closure* NewPermanentCallback(void (*function)()) {
- return new internal::FunctionClosure0(function, false);
-}
-
-// See Closure.
-template <typename Class>
-inline Closure* NewCallback(Class* object, void (Class::*method)()) {
- return new internal::MethodClosure0<Class>(object, method, true);
-}
-
-// See Closure.
-template <typename Class>
-inline Closure* NewPermanentCallback(Class* object, void (Class::*method)()) {
- return new internal::MethodClosure0<Class>(object, method, false);
-}
-
-// See Closure.
-template <typename Arg1>
-inline Closure* NewCallback(void (*function)(Arg1),
- Arg1 arg1) {
- return new internal::FunctionClosure1<Arg1>(function, true, arg1);
-}
-
-// See Closure.
-template <typename Arg1>
-inline Closure* NewPermanentCallback(void (*function)(Arg1),
- Arg1 arg1) {
- return new internal::FunctionClosure1<Arg1>(function, false, arg1);
-}
-
-// See Closure.
-template <typename Class, typename Arg1>
-inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1),
- Arg1 arg1) {
- return new internal::MethodClosure1<Class, Arg1>(object, method, true, arg1);
-}
-
-// See Closure.
-template <typename Class, typename Arg1>
-inline Closure* NewPermanentCallback(Class* object, void (Class::*method)(Arg1),
- Arg1 arg1) {
- return new internal::MethodClosure1<Class, Arg1>(object, method, false, arg1);
-}
-
-// See Closure.
-template <typename Arg1, typename Arg2>
-inline Closure* NewCallback(void (*function)(Arg1, Arg2),
- Arg1 arg1, Arg2 arg2) {
- return new internal::FunctionClosure2<Arg1, Arg2>(
- function, true, arg1, arg2);
-}
-
-// See Closure.
-template <typename Arg1, typename Arg2>
-inline Closure* NewPermanentCallback(void (*function)(Arg1, Arg2),
- Arg1 arg1, Arg2 arg2) {
- return new internal::FunctionClosure2<Arg1, Arg2>(
- function, false, arg1, arg2);
-}
-
-// See Closure.
-template <typename Class, typename Arg1, typename Arg2>
-inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1, Arg2),
- Arg1 arg1, Arg2 arg2) {
- return new internal::MethodClosure2<Class, Arg1, Arg2>(
- object, method, true, arg1, arg2);
-}
-
-// See Closure.
-template <typename Class, typename Arg1, typename Arg2>
-inline Closure* NewPermanentCallback(
- Class* object, void (Class::*method)(Arg1, Arg2),
- Arg1 arg1, Arg2 arg2) {
- return new internal::MethodClosure2<Class, Arg1, Arg2>(
- object, method, false, arg1, arg2);
-}
-
-// A function which does nothing. Useful for creating no-op callbacks, e.g.:
-// Closure* nothing = NewCallback(&DoNothing);
-void LIBPROTOBUF_EXPORT DoNothing();
-
-// ===================================================================
-// emulates google3/base/mutex.h
-
-namespace internal {
-
-// A Mutex is a non-reentrant (aka non-recursive) mutex. At most one thread T
-// may hold a mutex at a given time. If T attempts to Lock() the same Mutex
-// while holding it, T will deadlock.
-class LIBPROTOBUF_EXPORT Mutex {
- public:
- // Create a Mutex that is not held by anybody.
- Mutex();
-
- // Destructor
- ~Mutex();
-
- // Block if necessary until this Mutex is free, then acquire it exclusively.
- void Lock();
-
- // Release this Mutex. Caller must hold it exclusively.
- void Unlock();
-
- // Crash if this Mutex is not held exclusively by this thread.
- // May fail to crash when it should; will never crash when it should not.
- void AssertHeld();
-
- private:
- struct Internal;
- Internal* mInternal;
-
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Mutex);
-};
-
-// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
-class LIBPROTOBUF_EXPORT MutexLock {
- public:
- explicit MutexLock(Mutex *mu) : mu_(mu) { this->mu_->Lock(); }
- ~MutexLock() { this->mu_->Unlock(); }
- private:
- Mutex *const mu_;
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLock);
-};
-
-// TODO(kenton): Implement these? Hard to implement portably.
-typedef MutexLock ReaderMutexLock;
-typedef MutexLock WriterMutexLock;
-
-// MutexLockMaybe is like MutexLock, but is a no-op when mu is NULL.
-class LIBPROTOBUF_EXPORT MutexLockMaybe {
- public:
- explicit MutexLockMaybe(Mutex *mu) :
- mu_(mu) { if (this->mu_ != NULL) { this->mu_->Lock(); } }
- ~MutexLockMaybe() { if (this->mu_ != NULL) { this->mu_->Unlock(); } }
- private:
- Mutex *const mu_;
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe);
-};
-
-} // namespace internal
-
-// We made these internal so that they would show up as such in the docs,
-// but we don't want to stick "internal::" in front of them everywhere.
-using internal::Mutex;
-using internal::MutexLock;
-using internal::ReaderMutexLock;
-using internal::WriterMutexLock;
-using internal::MutexLockMaybe;
// ===================================================================
// from google3/util/utf8/public/unilib.h
@@ -1179,9 +145,6 @@ LIBPROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len);
} // namespace internal
-// ===================================================================
-// from google3/util/endian/endian.h
-LIBPROTOBUF_EXPORT uint32 ghtonl(uint32 x);
// ===================================================================
// Shutdown support.
diff --git a/src/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc
index 5f458e98..f9e2cfd4 100644
--- a/src/google/protobuf/stubs/common_unittest.cc
+++ b/src/google/protobuf/stubs/common_unittest.cc
@@ -39,8 +39,6 @@
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
-#include "config.h"
-
namespace google {
namespace protobuf {
namespace {
diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h
index 5b6a073d..9a6b217a 100644..100755
--- a/src/google/protobuf/stubs/hash.h
+++ b/src/google/protobuf/stubs/hash.h
@@ -37,13 +37,119 @@
#include <string.h>
#include <google/protobuf/stubs/common.h>
-#include "config.h"
-#if defined(HAVE_HASH_MAP) && defined(HAVE_HASH_SET)
-#include HASH_MAP_H
-#include HASH_SET_H
+#define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1
+#define GOOGLE_PROTOBUF_HAVE_HASH_SET 1
+
+// Use C++11 unordered_{map|set} if available. Otherwise, libc++ always support
+// unordered_{map|set}
+#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X) || \
+ defined(_LIBCPP_VERSION)
+# define GOOGLE_PROTOBUF_HAS_CXX11_HASH
+
+// For XCode >= 4.6: the compiler is clang with libc++.
+// For earlier XCode version: the compiler is gcc-4.2.1 with libstdc++.
+// libc++ provides <unordered_map> and friends even in non C++11 mode,
+// and it does not provide the tr1 library. Therefore the following macro
+// checks against this special case.
+// Note that we should not test the __APPLE_CC__ version number or the
+// __clang__ macro, since the new compiler can still use -stdlib=libstdc++, in
+// which case <unordered_map> is not compilable without -std=c++11
+#elif defined(__APPLE_CC__)
+# if __GNUC__ >= 4
+# define GOOGLE_PROTOBUF_HAS_TR1
+# else
+// Not tested for gcc < 4... These setting can compile under 4.2.1 though.
+# define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx
+# include <ext/hash_map>
+# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
+# include <ext/hash_set>
+# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
+# endif
+
+// Version checks for gcc.
+#elif defined(__GNUC__)
+// For GCC 4.x+, use tr1::unordered_map/set; otherwise, follow the
+// instructions from:
+// https://gcc.gnu.org/onlinedocs/libstdc++/manual/backwards.html
+# if __GNUC__ >= 4
+# define GOOGLE_PROTOBUF_HAS_TR1
+# elif __GNUC__ >= 3
+# include <backward/hash_map>
+# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
+# include <backward/hash_set>
+# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
+# if __GNUC__ == 3 && __GNUC_MINOR__ == 0
+# define GOOGLE_PROTOBUF_HASH_NAMESPACE std // GCC 3.0
+# else
+# define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx // GCC 3.1 and later
+# endif
+# else
+# define GOOGLE_PROTOBUF_HASH_NAMESPACE
+# include <hash_map>
+# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
+# include <hash_set>
+# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
+# endif
+
+// Version checks for MSC.
+// Apparently Microsoft decided to move hash_map *back* to the std namespace in
+// MSVC 2010:
+// http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx
+// And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That
+// said, use unordered_map for MSVC 2010 and beyond is our safest bet.
+#elif defined(_MSC_VER)
+# if _MSC_VER >= 1600 // Since Visual Studio 2010
+# define GOOGLE_PROTOBUF_HAS_CXX11_HASH
+# define GOOGLE_PROTOBUF_HASH_COMPARE std::hash_compare
+# elif _MSC_VER >= 1500 // Since Visual Studio 2008
+# define GOOGLE_PROTOBUF_HAS_TR1
+# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
+# elif _MSC_VER >= 1310
+# define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext
+# include <hash_map>
+# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
+# include <hash_set>
+# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
+# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
+# else
+# define GOOGLE_PROTOBUF_HASH_NAMESPACE std
+# include <hash_map>
+# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
+# include <hash_set>
+# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
+# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
+# endif
+
+// **ADD NEW COMPILERS SUPPORT HERE.**
+// For other compilers, undefine the macro and fallback to use std::map, in
+// google/protobuf/stubs/hash.h
#else
-#define MISSING_HASH
+# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP
+# undef GOOGLE_PROTOBUF_HAVE_HASH_SET
+#endif
+
+#if defined(GOOGLE_PROTOBUF_HAS_CXX11_HASH)
+# define GOOGLE_PROTOBUF_HASH_NAMESPACE std
+# include <unordered_map>
+# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map
+# include <unordered_set>
+# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set
+#elif defined(GOOGLE_PROTOBUF_HAS_TR1)
+# define GOOGLE_PROTOBUF_HASH_NAMESPACE std::tr1
+# include <tr1/unordered_map>
+# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map
+# include <tr1/unordered_set>
+# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set
+#endif
+
+#undef GOOGLE_PROTOBUF_HAS_CXX11_HASH
+#undef GOOGLE_PROTOBUF_HAS_TR1
+
+#if defined(GOOGLE_PROTOBUF_HAVE_HASH_MAP) && \
+ defined(GOOGLE_PROTOBUF_HAVE_HASH_SET)
+#else
+#define GOOGLE_PROTOBUF_MISSING_HASH
#include <map>
#include <set>
#endif
@@ -51,7 +157,8 @@
namespace google {
namespace protobuf {
-#ifdef MISSING_HASH
+#ifdef GOOGLE_PROTOBUF_MISSING_HASH
+#undef GOOGLE_PROTOBUF_MISSING_HASH
// This system doesn't have hash_map or hash_set. Emulate them using map and
// set.
@@ -88,15 +195,20 @@ struct hash<const char*> {
template <typename Key, typename Data,
typename HashFcn = hash<Key>,
- typename EqualKey = int >
-class hash_map : public std::map<Key, Data, HashFcn> {
+ typename EqualKey = std::equal_to<Key>,
+ typename Alloc = std::allocator< std::pair<const Key, Data> > >
+class hash_map : public std::map<Key, Data, HashFcn, Alloc> {
+ typedef std::map<Key, Data, HashFcn, Alloc> BaseClass;
+
public:
- hash_map(int = 0) {}
+ hash_map(int a = 0, const HashFcn& b = HashFcn(),
+ const EqualKey& c = EqualKey(),
+ const Alloc& d = Alloc()) : BaseClass(b, d) {}
};
template <typename Key,
typename HashFcn = hash<Key>,
- typename EqualKey = int >
+ typename EqualKey = std::equal_to<Key> >
class hash_set : public std::set<Key, HashFcn> {
public:
hash_set(int = 0) {}
@@ -105,7 +217,7 @@ class hash_set : public std::set<Key, HashFcn> {
#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION)
template <typename Key>
-struct hash : public HASH_NAMESPACE::hash_compare<Key> {
+struct hash : public GOOGLE_PROTOBUF_HASH_COMPARE<Key> {
};
// MSVC's hash_compare<const char*> hashes based on the string contents but
@@ -119,23 +231,29 @@ class CstringLess {
template <>
struct hash<const char*>
- : public HASH_NAMESPACE::hash_compare<const char*, CstringLess> {
-};
+ : public GOOGLE_PROTOBUF_HASH_COMPARE<const char*, CstringLess> {};
template <typename Key, typename Data,
typename HashFcn = hash<Key>,
- typename EqualKey = int >
-class hash_map : public HASH_NAMESPACE::hash_map<
- Key, Data, HashFcn> {
+ typename EqualKey = std::equal_to<Key>,
+ typename Alloc = std::allocator< std::pair<const Key, Data> > >
+class hash_map
+ : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
+ Key, Data, HashFcn, EqualKey, Alloc> {
+ typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
+ Key, Data, HashFcn, EqualKey, Alloc> BaseClass;
+
public:
- hash_map(int = 0) {}
+ hash_map(int a = 0, const HashFcn& b = HashFcn(),
+ const EqualKey& c = EqualKey(),
+ const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {}
};
-template <typename Key,
- typename HashFcn = hash<Key>,
- typename EqualKey = int >
-class hash_set : public HASH_NAMESPACE::hash_set<
- Key, HashFcn> {
+template <typename Key, typename HashFcn = hash<Key>,
+ typename EqualKey = std::equal_to<Key> >
+class hash_set
+ : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
+ Key, HashFcn, EqualKey> {
public:
hash_set(int = 0) {}
};
@@ -143,7 +261,7 @@ class hash_set : public HASH_NAMESPACE::hash_set<
#else
template <typename Key>
-struct hash : public HASH_NAMESPACE::hash<Key> {
+struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash<Key> {
};
template <typename Key>
@@ -166,25 +284,39 @@ struct hash<const char*> {
}
};
+template<>
+struct hash<bool> {
+ size_t operator()(bool x) const {
+ return static_cast<size_t>(x);
+ }
+};
+
template <typename Key, typename Data,
typename HashFcn = hash<Key>,
- typename EqualKey = std::equal_to<Key> >
-class hash_map : public HASH_NAMESPACE::HASH_MAP_CLASS<
- Key, Data, HashFcn, EqualKey> {
+ typename EqualKey = std::equal_to<Key>,
+ typename Alloc = std::allocator< std::pair<const Key, Data> > >
+class hash_map
+ : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
+ Key, Data, HashFcn, EqualKey, Alloc> {
+ typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
+ Key, Data, HashFcn, EqualKey, Alloc> BaseClass;
+
public:
- hash_map(int = 0) {}
+ hash_map(int a = 0, const HashFcn& b = HashFcn(),
+ const EqualKey& c = EqualKey(),
+ const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {}
};
-template <typename Key,
- typename HashFcn = hash<Key>,
+template <typename Key, typename HashFcn = hash<Key>,
typename EqualKey = std::equal_to<Key> >
-class hash_set : public HASH_NAMESPACE::HASH_SET_CLASS<
- Key, HashFcn, EqualKey> {
+class hash_set
+ : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
+ Key, HashFcn, EqualKey> {
public:
hash_set(int = 0) {}
};
-#endif
+#endif // !GOOGLE_PROTOBUF_MISSING_HASH
template <>
struct hash<string> {
@@ -194,7 +326,7 @@ struct hash<string> {
static const size_t bucket_size = 4;
static const size_t min_buckets = 8;
- inline size_t operator()(const string& a, const string& b) const {
+ inline bool operator()(const string& a, const string& b) const {
return a < b;
}
};
@@ -212,7 +344,7 @@ struct hash<pair<First, Second> > {
static const size_t bucket_size = 4;
static const size_t min_buckets = 8;
- inline size_t operator()(const pair<First, Second>& a,
+ inline bool operator()(const pair<First, Second>& a,
const pair<First, Second>& b) const {
return a < b;
}
diff --git a/src/google/protobuf/stubs/logging.h b/src/google/protobuf/stubs/logging.h
new file mode 100644
index 00000000..330d33d2
--- /dev/null
+++ b/src/google/protobuf/stubs/logging.h
@@ -0,0 +1,235 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_STUBS_LOGGING_H_
+#define GOOGLE_PROTOBUF_STUBS_LOGGING_H_
+
+#include <google/protobuf/stubs/macros.h>
+#include <google/protobuf/stubs/port.h>
+
+// ===================================================================
+// emulates google3/base/logging.h
+
+namespace google {
+namespace protobuf {
+
+enum LogLevel {
+ LOGLEVEL_INFO, // Informational. This is never actually used by
+ // libprotobuf.
+ LOGLEVEL_WARNING, // Warns about issues that, although not technically a
+ // problem now, could cause problems in the future. For
+ // example, a // warning will be printed when parsing a
+ // message that is near the message size limit.
+ LOGLEVEL_ERROR, // An error occurred which should never happen during
+ // normal use.
+ LOGLEVEL_FATAL, // An error occurred from which the library cannot
+ // recover. This usually indicates a programming error
+ // in the code which calls the library, especially when
+ // compiled in debug mode.
+
+#ifdef NDEBUG
+ LOGLEVEL_DFATAL = LOGLEVEL_ERROR
+#else
+ LOGLEVEL_DFATAL = LOGLEVEL_FATAL
+#endif
+};
+
+class StringPiece;
+namespace util {
+class Status;
+}
+namespace internal {
+
+class LogFinisher;
+
+class LIBPROTOBUF_EXPORT LogMessage {
+ public:
+ LogMessage(LogLevel level, const char* filename, int line);
+ ~LogMessage();
+
+ LogMessage& operator<<(const std::string& value);
+ LogMessage& operator<<(const char* value);
+ LogMessage& operator<<(char value);
+ LogMessage& operator<<(int value);
+ LogMessage& operator<<(unsigned int value);
+ LogMessage& operator<<(long value);
+ LogMessage& operator<<(unsigned long value);
+ LogMessage& operator<<(long long value);
+ LogMessage& operator<<(unsigned long long value);
+ LogMessage& operator<<(double value);
+ LogMessage& operator<<(void* value);
+ LogMessage& operator<<(const StringPiece& value);
+ LogMessage& operator<<(const ::google::protobuf::util::Status& status);
+
+ private:
+ friend class LogFinisher;
+ void Finish();
+
+ LogLevel level_;
+ const char* filename_;
+ int line_;
+ std::string message_;
+};
+
+// Used to make the entire "LOG(BLAH) << etc." expression have a void return
+// type and print a newline after each message.
+class LIBPROTOBUF_EXPORT LogFinisher {
+ public:
+ void operator=(LogMessage& other);
+};
+
+template<typename T>
+bool IsOk(T status) { return status.ok(); }
+template<>
+inline bool IsOk(bool status) { return status; }
+
+} // namespace internal
+
+// Undef everything in case we're being mixed with some other Google library
+// which already defined them itself. Presumably all Google libraries will
+// support the same syntax for these so it should not be a big deal if they
+// end up using our definitions instead.
+#undef GOOGLE_LOG
+#undef GOOGLE_LOG_IF
+
+#undef GOOGLE_CHECK
+#undef GOOGLE_CHECK_OK
+#undef GOOGLE_CHECK_EQ
+#undef GOOGLE_CHECK_NE
+#undef GOOGLE_CHECK_LT
+#undef GOOGLE_CHECK_LE
+#undef GOOGLE_CHECK_GT
+#undef GOOGLE_CHECK_GE
+#undef GOOGLE_CHECK_NOTNULL
+
+#undef GOOGLE_DLOG
+#undef GOOGLE_DCHECK
+#undef GOOGLE_DCHECK_OK
+#undef GOOGLE_DCHECK_EQ
+#undef GOOGLE_DCHECK_NE
+#undef GOOGLE_DCHECK_LT
+#undef GOOGLE_DCHECK_LE
+#undef GOOGLE_DCHECK_GT
+#undef GOOGLE_DCHECK_GE
+
+#define GOOGLE_LOG(LEVEL) \
+ ::google::protobuf::internal::LogFinisher() = \
+ ::google::protobuf::internal::LogMessage( \
+ ::google::protobuf::LOGLEVEL_##LEVEL, __FILE__, __LINE__)
+#define GOOGLE_LOG_IF(LEVEL, CONDITION) \
+ !(CONDITION) ? (void)0 : GOOGLE_LOG(LEVEL)
+
+#define GOOGLE_CHECK(EXPRESSION) \
+ GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": "
+#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(::google::protobuf::internal::IsOk(A))
+#define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B))
+#define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B))
+#define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B))
+#define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK((A) <= (B))
+#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) > (B))
+#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B))
+
+namespace internal {
+template<typename T>
+T* CheckNotNull(const char* /* file */, int /* line */,
+ const char* name, T* val) {
+ if (val == NULL) {
+ GOOGLE_LOG(FATAL) << name;
+ }
+ return val;
+}
+} // namespace internal
+#define GOOGLE_CHECK_NOTNULL(A) \
+ ::google::protobuf::internal::CheckNotNull(\
+ __FILE__, __LINE__, "'" #A "' must not be NULL", (A))
+
+#ifdef NDEBUG
+
+#define GOOGLE_DLOG GOOGLE_LOG_IF(INFO, false)
+
+#define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION)
+#define GOOGLE_DCHECK_OK(E) GOOGLE_DCHECK(::google::protobuf::internal::IsOk(E))
+#define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK((A) == (B))
+#define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK((A) != (B))
+#define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK((A) < (B))
+#define GOOGLE_DCHECK_LE(A, B) GOOGLE_DCHECK((A) <= (B))
+#define GOOGLE_DCHECK_GT(A, B) GOOGLE_DCHECK((A) > (B))
+#define GOOGLE_DCHECK_GE(A, B) GOOGLE_DCHECK((A) >= (B))
+
+#else // NDEBUG
+
+#define GOOGLE_DLOG GOOGLE_LOG
+
+#define GOOGLE_DCHECK GOOGLE_CHECK
+#define GOOGLE_DCHECK_OK GOOGLE_CHECK_OK
+#define GOOGLE_DCHECK_EQ GOOGLE_CHECK_EQ
+#define GOOGLE_DCHECK_NE GOOGLE_CHECK_NE
+#define GOOGLE_DCHECK_LT GOOGLE_CHECK_LT
+#define GOOGLE_DCHECK_LE GOOGLE_CHECK_LE
+#define GOOGLE_DCHECK_GT GOOGLE_CHECK_GT
+#define GOOGLE_DCHECK_GE GOOGLE_CHECK_GE
+
+#endif // !NDEBUG
+
+typedef void LogHandler(LogLevel level, const char* filename, int line,
+ const std::string& message);
+
+// The protobuf library sometimes writes warning and error messages to
+// stderr. These messages are primarily useful for developers, but may
+// also help end users figure out a problem. If you would prefer that
+// these messages be sent somewhere other than stderr, call SetLogHandler()
+// to set your own handler. This returns the old handler. Set the handler
+// to NULL to ignore log messages (but see also LogSilencer, below).
+//
+// Obviously, SetLogHandler is not thread-safe. You should only call it
+// at initialization time, and probably not from library code. If you
+// simply want to suppress log messages temporarily (e.g. because you
+// have some code that tends to trigger them frequently and you know
+// the warnings are not important to you), use the LogSilencer class
+// below.
+LIBPROTOBUF_EXPORT LogHandler* SetLogHandler(LogHandler* new_func);
+
+// Create a LogSilencer if you want to temporarily suppress all log
+// messages. As long as any LogSilencer objects exist, non-fatal
+// log messages will be discarded (the current LogHandler will *not*
+// be called). Constructing a LogSilencer is thread-safe. You may
+// accidentally suppress log messages occurring in another thread, but
+// since messages are generally for debugging purposes only, this isn't
+// a big deal. If you want to intercept log messages, use SetLogHandler().
+class LIBPROTOBUF_EXPORT LogSilencer {
+ public:
+ LogSilencer();
+ ~LogSilencer();
+};
+
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_LOGGING_H_
diff --git a/src/google/protobuf/stubs/macros.h b/src/google/protobuf/stubs/macros.h
new file mode 100644
index 00000000..0e9a9ec1
--- /dev/null
+++ b/src/google/protobuf/stubs/macros.h
@@ -0,0 +1,168 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_MACROS_H__
+#define GOOGLE_PROTOBUF_MACROS_H__
+
+#include <google/protobuf/stubs/port.h>
+
+namespace google {
+namespace protobuf {
+
+#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
+#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+
+#undef GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS
+#define GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+ TypeName(); \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+
+// ===================================================================
+// from google3/base/basictypes.h
+
+// The GOOGLE_ARRAYSIZE(arr) macro returns the # of elements in an array arr.
+// The expression is a compile-time constant, and therefore can be
+// used in defining new arrays, for example.
+//
+// GOOGLE_ARRAYSIZE catches a few type errors. If you see a compiler error
+//
+// "warning: division by zero in ..."
+//
+// when using GOOGLE_ARRAYSIZE, you are (wrongfully) giving it a pointer.
+// You should only use GOOGLE_ARRAYSIZE on statically allocated arrays.
+//
+// The following comments are on the implementation details, and can
+// be ignored by the users.
+//
+// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in
+// the array) and sizeof(*(arr)) (the # of bytes in one array
+// element). If the former is divisible by the latter, perhaps arr is
+// indeed an array, in which case the division result is the # of
+// elements in the array. Otherwise, arr cannot possibly be an array,
+// and we generate a compiler error to prevent the code from
+// compiling.
+//
+// Since the size of bool is implementation-defined, we need to cast
+// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
+// result has type size_t.
+//
+// This macro is not perfect as it wrongfully accepts certain
+// pointers, namely where the pointer size is divisible by the pointee
+// size. Since all our code has to go through a 32-bit compiler,
+// where a pointer is 4 bytes, this means all pointers to a type whose
+// size is 3 or greater than 4 will be (righteously) rejected.
+//
+// Kudos to Jorg Brown for this simple and elegant implementation.
+
+#undef GOOGLE_ARRAYSIZE
+#define GOOGLE_ARRAYSIZE(a) \
+ ((sizeof(a) / sizeof(*(a))) / \
+ static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
+
+// The COMPILE_ASSERT macro can be used to verify that a compile time
+// expression is true. For example, you could use it to verify the
+// size of a static array:
+//
+// COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
+// content_type_names_incorrect_size);
+//
+// or to make sure a struct is smaller than a certain size:
+//
+// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
+//
+// The second argument to the macro is the name of the variable. If
+// the expression is false, most compilers will issue a warning/error
+// containing the name of the variable.
+
+namespace internal {
+
+template <bool>
+struct CompileAssert {
+};
+
+} // namespace internal
+
+#undef GOOGLE_COMPILE_ASSERT
+#if __cplusplus >= 201103L
+#define GOOGLE_COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
+#else
+#define GOOGLE_COMPILE_ASSERT(expr, msg) \
+ ::google::protobuf::internal::CompileAssert<(bool(expr))> \
+ msg[bool(expr) ? 1 : -1]; \
+ (void)msg
+// Implementation details of COMPILE_ASSERT:
+//
+// - COMPILE_ASSERT works by defining an array type that has -1
+// elements (and thus is invalid) when the expression is false.
+//
+// - The simpler definition
+//
+// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
+//
+// does not work, as gcc supports variable-length arrays whose sizes
+// are determined at run-time (this is gcc's extension and not part
+// of the C++ standard). As a result, gcc fails to reject the
+// following code with the simple definition:
+//
+// int foo;
+// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
+// // not a compile-time constant.
+//
+// - By using the type CompileAssert<(bool(expr))>, we ensures that
+// expr is a compile-time constant. (Template arguments must be
+// determined at compile-time.)
+//
+// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
+// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
+//
+// CompileAssert<bool(expr)>
+//
+// instead, these compilers will refuse to compile
+//
+// COMPILE_ASSERT(5 > 0, some_message);
+//
+// (They seem to think the ">" in "5 > 0" marks the end of the
+// template argument list.)
+//
+// - The array size is (bool(expr) ? 1 : -1), instead of simply
+//
+// ((expr) ? 1 : -1).
+//
+// This is to avoid running into a bug in MS VC 7.1, which
+// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
+#endif // __cplusplus >= 201103L
+
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_MACROS_H__
diff --git a/src/google/protobuf/stubs/mathlimits.cc b/src/google/protobuf/stubs/mathlimits.cc
new file mode 100644
index 00000000..0373b2bb
--- /dev/null
+++ b/src/google/protobuf/stubs/mathlimits.cc
@@ -0,0 +1,144 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// All Rights Reserved.
+//
+// Author: Maxim Lifantsev
+//
+
+#include <google/protobuf/stubs/mathlimits.h>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+// MSVC++ 2005 and older compilers think the header declaration was a
+// definition, and erroneously flag these as a duplicate definition.
+#if defined(COMPILER_MSVC) || __cpluscplus < 201103L
+
+#define DEF_COMMON_LIMITS(Type)
+#define DEF_UNSIGNED_INT_LIMITS(Type)
+#define DEF_SIGNED_INT_LIMITS(Type)
+#define DEF_PRECISION_LIMITS(Type)
+
+#else
+
+#define DEF_COMMON_LIMITS(Type) \
+const bool MathLimits<Type>::kIsSigned; \
+const bool MathLimits<Type>::kIsInteger; \
+const int MathLimits<Type>::kMin10Exp; \
+const int MathLimits<Type>::kMax10Exp;
+
+#define DEF_UNSIGNED_INT_LIMITS(Type) \
+DEF_COMMON_LIMITS(Type) \
+const Type MathLimits<Type>::kPosMin; \
+const Type MathLimits<Type>::kPosMax; \
+const Type MathLimits<Type>::kMin; \
+const Type MathLimits<Type>::kMax; \
+const Type MathLimits<Type>::kEpsilon; \
+const Type MathLimits<Type>::kStdError;
+
+#define DEF_SIGNED_INT_LIMITS(Type) \
+DEF_UNSIGNED_INT_LIMITS(Type) \
+const Type MathLimits<Type>::kNegMin; \
+const Type MathLimits<Type>::kNegMax;
+
+#define DEF_PRECISION_LIMITS(Type) \
+const int MathLimits<Type>::kPrecisionDigits;
+
+#endif // not COMPILER_MSVC
+
+// http://en.wikipedia.org/wiki/Quadruple_precision_floating-point_format#Double-double_arithmetic
+// With some compilers (gcc 4.6.x) on some platforms (powerpc64),
+// "long double" is implemented as a pair of double: "double double" format.
+// This causes a problem with epsilon (eps).
+// eps is the smallest positive number such that 1.0 + eps > 1.0
+//
+// Normal format: 1.0 + e = 1.0...01 // N-1 zeros for N fraction bits
+// D-D format: 1.0 + e = 1.000...0001 // epsilon can be very small
+//
+// In the normal format, 1.0 + e has to fit in one stretch of bits.
+// The maximum rounding error is half of eps.
+//
+// In the double-double format, 1.0 + e splits across two doubles:
+// 1.0 in the high double, e in the low double, and they do not have to
+// be contiguous. The maximum rounding error on a value close to 1.0 is
+// much larger than eps.
+//
+// Some code checks for errors by comparing a computed value to a golden
+// value +/- some multiple of the maximum rounding error. The maximum
+// rounding error is not available so we use eps as an approximation
+// instead. That fails when long double is in the double-double format.
+// Therefore, we define kStdError as a multiple of
+// max(DBL_EPSILON * DBL_EPSILON, kEpsilon) rather than a multiple of kEpsilon.
+
+#define DEF_FP_LIMITS(Type, PREFIX) \
+DEF_COMMON_LIMITS(Type) \
+const Type MathLimits<Type>::kPosMin = PREFIX##_MIN; \
+const Type MathLimits<Type>::kPosMax = PREFIX##_MAX; \
+const Type MathLimits<Type>::kMin = -MathLimits<Type>::kPosMax; \
+const Type MathLimits<Type>::kMax = MathLimits<Type>::kPosMax; \
+const Type MathLimits<Type>::kNegMin = -MathLimits<Type>::kPosMin; \
+const Type MathLimits<Type>::kNegMax = -MathLimits<Type>::kPosMax; \
+const Type MathLimits<Type>::kEpsilon = PREFIX##_EPSILON; \
+/* 32 is 5 bits of mantissa error; should be adequate for common errors */ \
+const Type MathLimits<Type>::kStdError = \
+ 32 * (DBL_EPSILON * DBL_EPSILON > MathLimits<Type>::kEpsilon \
+ ? DBL_EPSILON * DBL_EPSILON : MathLimits<Type>::kEpsilon); \
+DEF_PRECISION_LIMITS(Type) \
+const Type MathLimits<Type>::kNaN = HUGE_VAL - HUGE_VAL; \
+const Type MathLimits<Type>::kPosInf = HUGE_VAL; \
+const Type MathLimits<Type>::kNegInf = -HUGE_VAL;
+
+// The following are *not* casts!
+DEF_SIGNED_INT_LIMITS(int8)
+DEF_SIGNED_INT_LIMITS(int16) // NOLINT(readability/casting)
+DEF_SIGNED_INT_LIMITS(int32) // NOLINT(readability/casting)
+DEF_SIGNED_INT_LIMITS(int64) // NOLINT(readability/casting)
+DEF_UNSIGNED_INT_LIMITS(uint8)
+DEF_UNSIGNED_INT_LIMITS(uint16) // NOLINT(readability/casting)
+DEF_UNSIGNED_INT_LIMITS(uint32) // NOLINT(readability/casting)
+DEF_UNSIGNED_INT_LIMITS(uint64) // NOLINT(readability/casting)
+
+DEF_SIGNED_INT_LIMITS(long int)
+DEF_UNSIGNED_INT_LIMITS(unsigned long int)
+
+DEF_FP_LIMITS(float, FLT)
+DEF_FP_LIMITS(double, DBL)
+DEF_FP_LIMITS(long double, LDBL);
+
+#undef DEF_COMMON_LIMITS
+#undef DEF_SIGNED_INT_LIMITS
+#undef DEF_UNSIGNED_INT_LIMITS
+#undef DEF_FP_LIMITS
+#undef DEF_PRECISION_LIMITS
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/mathlimits.h b/src/google/protobuf/stubs/mathlimits.h
new file mode 100644
index 00000000..d9846940
--- /dev/null
+++ b/src/google/protobuf/stubs/mathlimits.h
@@ -0,0 +1,279 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// All Rights Reserved.
+//
+// Author: Maxim Lifantsev
+//
+// Useful integer and floating point limits and type traits.
+//
+// This partially replaces/duplictes numeric_limits<> from <limits>.
+// We get a Google-style class that we have a greater control over
+// and thus can add new features to it or fix whatever happens to be broken in
+// numeric_limits for the compilers we use.
+//
+
+#ifndef UTIL_MATH_MATHLIMITS_H__
+#define UTIL_MATH_MATHLIMITS_H__
+
+// <math.h> lacks a lot of prototypes. However, this file needs <math.h> to
+// access old-fashioned isinf et al. Even worse more: this file must not
+// include <cmath> because that breaks the definition of isinf with gcc 4.9.
+//
+// TODO(mec): after C++11 everywhere, use <cmath> and std::isinf in this file.
+#include <math.h>
+#include <string.h>
+
+#include <cfloat>
+
+#include <google/protobuf/stubs/common.h>
+
+// ========================================================================= //
+
+// Useful integer and floating point limits and type traits.
+// This is just for the documentation;
+// real members are defined in our specializations below.
+namespace google {
+namespace protobuf {
+template<typename T> struct MathLimits {
+ // Type name.
+ typedef T Type;
+ // Unsigned version of the Type with the same byte size.
+ // Same as Type for floating point and unsigned types.
+ typedef T UnsignedType;
+ // If the type supports negative values.
+ static const bool kIsSigned;
+ // If the type supports only integer values.
+ static const bool kIsInteger;
+ // Magnitude-wise smallest representable positive value.
+ static const Type kPosMin;
+ // Magnitude-wise largest representable positive value.
+ static const Type kPosMax;
+ // Smallest representable value.
+ static const Type kMin;
+ // Largest representable value.
+ static const Type kMax;
+ // Magnitude-wise smallest representable negative value.
+ // Present only if kIsSigned.
+ static const Type kNegMin;
+ // Magnitude-wise largest representable negative value.
+ // Present only if kIsSigned.
+ static const Type kNegMax;
+ // Smallest integer x such that 10^x is representable.
+ static const int kMin10Exp;
+ // Largest integer x such that 10^x is representable.
+ static const int kMax10Exp;
+ // Smallest positive value such that Type(1) + kEpsilon != Type(1)
+ static const Type kEpsilon;
+ // Typical rounding error that is enough to cover
+ // a few simple floating-point operations.
+ // Slightly larger than kEpsilon to account for a few rounding errors.
+ // Is zero if kIsInteger.
+ static const Type kStdError;
+ // Number of decimal digits of mantissa precision.
+ // Present only if !kIsInteger.
+ static const int kPrecisionDigits;
+ // Not a number, i.e. result of 0/0.
+ // Present only if !kIsInteger.
+ static const Type kNaN;
+ // Positive infinity, i.e. result of 1/0.
+ // Present only if !kIsInteger.
+ static const Type kPosInf;
+ // Negative infinity, i.e. result of -1/0.
+ // Present only if !kIsInteger.
+ static const Type kNegInf;
+
+ // NOTE: Special floating point values behave
+ // in a special (but mathematically-logical) way
+ // in terms of (in)equalty comparison and mathematical operations
+ // -- see out unittest for examples.
+
+ // Special floating point value testers.
+ // Present in integer types for convenience.
+ static bool IsFinite(const Type x);
+ static bool IsNaN(const Type x);
+ static bool IsInf(const Type x);
+ static bool IsPosInf(const Type x);
+ static bool IsNegInf(const Type x);
+};
+
+// ========================================================================= //
+
+// All #define-s below are simply to refactor the declarations of
+// MathLimits template specializations.
+// They are all #undef-ined below.
+
+// The hoop-jumping in *_INT_(MAX|MIN) below is so that the compiler does not
+// get an overflow while computing the constants.
+
+#define SIGNED_INT_MAX(Type) \
+ (((Type(1) << (sizeof(Type)*8 - 2)) - 1) + (Type(1) << (sizeof(Type)*8 - 2)))
+
+#define SIGNED_INT_MIN(Type) \
+ (-(Type(1) << (sizeof(Type)*8 - 2)) - (Type(1) << (sizeof(Type)*8 - 2)))
+
+#define UNSIGNED_INT_MAX(Type) \
+ (((Type(1) << (sizeof(Type)*8 - 1)) - 1) + (Type(1) << (sizeof(Type)*8 - 1)))
+
+// Compile-time selected log10-related constants for integer types.
+#define SIGNED_MAX_10_EXP(Type) \
+ (sizeof(Type) == 1 ? 2 : ( \
+ sizeof(Type) == 2 ? 4 : ( \
+ sizeof(Type) == 4 ? 9 : ( \
+ sizeof(Type) == 8 ? 18 : -1))))
+
+#define UNSIGNED_MAX_10_EXP(Type) \
+ (sizeof(Type) == 1 ? 2 : ( \
+ sizeof(Type) == 2 ? 4 : ( \
+ sizeof(Type) == 4 ? 9 : ( \
+ sizeof(Type) == 8 ? 19 : -1))))
+
+#define DECL_INT_LIMIT_FUNCS \
+ static bool IsFinite(const Type /*x*/) { return true; } \
+ static bool IsNaN(const Type /*x*/) { return false; } \
+ static bool IsInf(const Type /*x*/) { return false; } \
+ static bool IsPosInf(const Type /*x*/) { return false; } \
+ static bool IsNegInf(const Type /*x*/) { return false; }
+
+#define DECL_SIGNED_INT_LIMITS(IntType, UnsignedIntType) \
+template<> \
+struct LIBPROTOBUF_EXPORT MathLimits<IntType> { \
+ typedef IntType Type; \
+ typedef UnsignedIntType UnsignedType; \
+ static const bool kIsSigned = true; \
+ static const bool kIsInteger = true; \
+ static const Type kPosMin = 1; \
+ static const Type kPosMax = SIGNED_INT_MAX(Type); \
+ static const Type kMin = SIGNED_INT_MIN(Type); \
+ static const Type kMax = kPosMax; \
+ static const Type kNegMin = -1; \
+ static const Type kNegMax = kMin; \
+ static const int kMin10Exp = 0; \
+ static const int kMax10Exp = SIGNED_MAX_10_EXP(Type); \
+ static const Type kEpsilon = 1; \
+ static const Type kStdError = 0; \
+ DECL_INT_LIMIT_FUNCS \
+};
+
+#define DECL_UNSIGNED_INT_LIMITS(IntType) \
+template<> \
+struct LIBPROTOBUF_EXPORT MathLimits<IntType> { \
+ typedef IntType Type; \
+ typedef IntType UnsignedType; \
+ static const bool kIsSigned = false; \
+ static const bool kIsInteger = true; \
+ static const Type kPosMin = 1; \
+ static const Type kPosMax = UNSIGNED_INT_MAX(Type); \
+ static const Type kMin = 0; \
+ static const Type kMax = kPosMax; \
+ static const int kMin10Exp = 0; \
+ static const int kMax10Exp = UNSIGNED_MAX_10_EXP(Type); \
+ static const Type kEpsilon = 1; \
+ static const Type kStdError = 0; \
+ DECL_INT_LIMIT_FUNCS \
+};
+
+DECL_SIGNED_INT_LIMITS(signed char, unsigned char)
+DECL_SIGNED_INT_LIMITS(signed short int, unsigned short int)
+DECL_SIGNED_INT_LIMITS(signed int, unsigned int)
+DECL_SIGNED_INT_LIMITS(signed long int, unsigned long int)
+DECL_SIGNED_INT_LIMITS(signed long long int, unsigned long long int)
+DECL_UNSIGNED_INT_LIMITS(unsigned char)
+DECL_UNSIGNED_INT_LIMITS(unsigned short int)
+DECL_UNSIGNED_INT_LIMITS(unsigned int)
+DECL_UNSIGNED_INT_LIMITS(unsigned long int)
+DECL_UNSIGNED_INT_LIMITS(unsigned long long int)
+
+#undef DECL_SIGNED_INT_LIMITS
+#undef DECL_UNSIGNED_INT_LIMITS
+#undef SIGNED_INT_MAX
+#undef SIGNED_INT_MIN
+#undef UNSIGNED_INT_MAX
+#undef SIGNED_MAX_10_EXP
+#undef UNSIGNED_MAX_10_EXP
+#undef DECL_INT_LIMIT_FUNCS
+
+// ========================================================================= //
+#ifdef WIN32 // Lacks built-in isnan() and isinf()
+#define DECL_FP_LIMIT_FUNCS \
+ static bool IsFinite(const Type x) { return _finite(x); } \
+ static bool IsNaN(const Type x) { return _isnan(x); } \
+ static bool IsInf(const Type x) { return (_fpclass(x) & (_FPCLASS_NINF | _FPCLASS_PINF)) != 0; } \
+ static bool IsPosInf(const Type x) { return _fpclass(x) == _FPCLASS_PINF; } \
+ static bool IsNegInf(const Type x) { return _fpclass(x) == _FPCLASS_NINF; }
+#else
+#define DECL_FP_LIMIT_FUNCS \
+ static bool IsFinite(const Type x) { return !isinf(x) && !isnan(x); } \
+ static bool IsNaN(const Type x) { return isnan(x); } \
+ static bool IsInf(const Type x) { return isinf(x); } \
+ static bool IsPosInf(const Type x) { return isinf(x) && x > 0; } \
+ static bool IsNegInf(const Type x) { return isinf(x) && x < 0; }
+#endif
+
+// We can't put floating-point constant values in the header here because
+// such constants are not considered to be primitive-type constants by gcc.
+// CAVEAT: Hence, they are going to be initialized only during
+// the global objects construction time.
+#define DECL_FP_LIMITS(FP_Type, PREFIX) \
+template<> \
+struct LIBPROTOBUF_EXPORT MathLimits<FP_Type> { \
+ typedef FP_Type Type; \
+ typedef FP_Type UnsignedType; \
+ static const bool kIsSigned = true; \
+ static const bool kIsInteger = false; \
+ static const Type kPosMin; \
+ static const Type kPosMax; \
+ static const Type kMin; \
+ static const Type kMax; \
+ static const Type kNegMin; \
+ static const Type kNegMax; \
+ static const int kMin10Exp = PREFIX##_MIN_10_EXP; \
+ static const int kMax10Exp = PREFIX##_MAX_10_EXP; \
+ static const Type kEpsilon; \
+ static const Type kStdError; \
+ static const int kPrecisionDigits = PREFIX##_DIG; \
+ static const Type kNaN; \
+ static const Type kPosInf; \
+ static const Type kNegInf; \
+ DECL_FP_LIMIT_FUNCS \
+};
+
+DECL_FP_LIMITS(float, FLT)
+DECL_FP_LIMITS(double, DBL)
+DECL_FP_LIMITS(long double, LDBL)
+
+#undef DECL_FP_LIMITS
+#undef DECL_FP_LIMIT_FUNCS
+
+// ========================================================================= //
+} // namespace protobuf
+} // namespace google
+
+#endif // UTIL_MATH_MATHLIMITS_H__
diff --git a/src/google/protobuf/stubs/mathutil.h b/src/google/protobuf/stubs/mathutil.h
new file mode 100644
index 00000000..99c4d452
--- /dev/null
+++ b/src/google/protobuf/stubs/mathutil.h
@@ -0,0 +1,150 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifndef GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_
+#define GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_
+
+#include <float.h>
+#include <math.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/mathlimits.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<typename T>
+bool IsNan(T value) {
+ return false;
+}
+template<>
+inline bool IsNan(float value) { return isnan(value); }
+template<>
+inline bool IsNan(double value) { return isnan(value); }
+
+template<typename T>
+bool AlmostEquals(T a, T b) {
+ return a == b;
+}
+template<>
+inline bool AlmostEquals(float a, float b) {
+ return fabs(a - b) < 32 * FLT_EPSILON;
+}
+
+template<>
+inline bool AlmostEquals(double a, double b) {
+ return fabs(a - b) < 32 * DBL_EPSILON;
+}
+} // namespace internal
+
+class MathUtil {
+ public:
+ template<typename T>
+ static T Sign(T value) {
+ if (value == T(0) || ::google::protobuf::internal::IsNan<T>(value)) {
+ return value;
+ }
+ return value > T(0) ? value : -value;
+ }
+
+ template<typename T>
+ static bool AlmostEquals(T a, T b) {
+ return ::google::protobuf::internal::AlmostEquals(a, b);
+ }
+
+ // Largest of two values.
+ // Works correctly for special floating point values.
+ // Note: 0.0 and -0.0 are not differentiated by Max (Max(0.0, -0.0) is -0.0),
+ // which should be OK because, although they (can) have different
+ // bit representation, they are observably the same when examined
+ // with arithmetic and (in)equality operators.
+ template<typename T>
+ static T Max(const T x, const T y) {
+ return MathLimits<T>::IsNaN(x) || x > y ? x : y;
+ }
+
+ // Absolute value of x
+ // Works correctly for unsigned types and
+ // for special floating point values.
+ // Note: 0.0 and -0.0 are not differentiated by Abs (Abs(0.0) is -0.0),
+ // which should be OK: see the comment for Max above.
+ template<typename T>
+ static T Abs(const T x) {
+ return x > T(0) ? x : -x;
+ }
+
+ // Absolute value of the difference between two numbers.
+ // Works correctly for signed types and special floating point values.
+ template<typename T>
+ static typename MathLimits<T>::UnsignedType AbsDiff(const T x, const T y) {
+ // Carries out arithmetic as unsigned to avoid overflow.
+ typedef typename MathLimits<T>::UnsignedType R;
+ return x > y ? R(x) - R(y) : R(y) - R(x);
+ }
+
+ // If two (usually floating point) numbers are within a certain
+ // fraction of their magnitude or within a certain absolute margin of error.
+ // This is the same as the following but faster:
+ // WithinFraction(x, y, fraction) || WithinMargin(x, y, margin)
+ // E.g. WithinFraction(0.0, 1e-10, 1e-5) is false but
+ // WithinFractionOrMargin(0.0, 1e-10, 1e-5, 1e-5) is true.
+ template<typename T>
+ static bool WithinFractionOrMargin(const T x, const T y,
+ const T fraction, const T margin);
+};
+
+template<typename T>
+bool MathUtil::WithinFractionOrMargin(const T x, const T y,
+ const T fraction, const T margin) {
+ // Not just "0 <= fraction" to fool the compiler for unsigned types.
+ GOOGLE_DCHECK((T(0) < fraction || T(0) == fraction) &&
+ fraction < T(1) &&
+ margin >= T(0));
+
+ // Template specialization will convert the if() condition to a constant,
+ // which will cause the compiler to generate code for either the "if" part
+ // or the "then" part. In this way we avoid a compiler warning
+ // about a potential integer overflow in crosstool v12 (gcc 4.3.1).
+ if (MathLimits<T>::kIsInteger) {
+ return x == y;
+ } else {
+ // IsFinite checks are to make kPosInf and kNegInf not within fraction
+ if (!MathLimits<T>::IsFinite(x) && !MathLimits<T>::IsFinite(y)) {
+ return false;
+ }
+ T relative_margin = static_cast<T>(fraction * Max(Abs(x), Abs(y)));
+ return AbsDiff(x, y) <= Max(margin, relative_margin);
+ }
+}
+
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_
diff --git a/src/google/protobuf/stubs/mutex.h b/src/google/protobuf/stubs/mutex.h
new file mode 100644
index 00000000..7ef1cb69
--- /dev/null
+++ b/src/google/protobuf/stubs/mutex.h
@@ -0,0 +1,148 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_STUBS_MUTEX_H_
+#define GOOGLE_PROTOBUF_STUBS_MUTEX_H_
+
+#ifdef GOOGLE_PROTOBUF_NO_THREADLOCAL
+#include <pthread.h>
+#endif
+
+#include <google/protobuf/stubs/macros.h>
+
+// ===================================================================
+// emulates google3/base/mutex.h
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// A Mutex is a non-reentrant (aka non-recursive) mutex. At most one thread T
+// may hold a mutex at a given time. If T attempts to Lock() the same Mutex
+// while holding it, T will deadlock.
+class LIBPROTOBUF_EXPORT Mutex {
+ public:
+ // Create a Mutex that is not held by anybody.
+ Mutex();
+
+ // Destructor
+ ~Mutex();
+
+ // Block if necessary until this Mutex is free, then acquire it exclusively.
+ void Lock();
+
+ // Release this Mutex. Caller must hold it exclusively.
+ void Unlock();
+
+ // Crash if this Mutex is not held exclusively by this thread.
+ // May fail to crash when it should; will never crash when it should not.
+ void AssertHeld();
+
+ private:
+ struct Internal;
+ Internal* mInternal;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Mutex);
+};
+
+// Undefine the macros to workaround the conflicts with Google internal
+// MutexLock implementation.
+// TODO(liujisi): Remove the undef once internal macros are removed.
+#undef MutexLock
+#undef ReaderMutexLock
+#undef WriterMutexLock
+#undef MutexLockMaybe
+
+// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
+class LIBPROTOBUF_EXPORT MutexLock {
+ public:
+ explicit MutexLock(Mutex *mu) : mu_(mu) { this->mu_->Lock(); }
+ ~MutexLock() { this->mu_->Unlock(); }
+ private:
+ Mutex *const mu_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLock);
+};
+
+// TODO(kenton): Implement these? Hard to implement portably.
+typedef MutexLock ReaderMutexLock;
+typedef MutexLock WriterMutexLock;
+
+// MutexLockMaybe is like MutexLock, but is a no-op when mu is NULL.
+class LIBPROTOBUF_EXPORT MutexLockMaybe {
+ public:
+ explicit MutexLockMaybe(Mutex *mu) :
+ mu_(mu) { if (this->mu_ != NULL) { this->mu_->Lock(); } }
+ ~MutexLockMaybe() { if (this->mu_ != NULL) { this->mu_->Unlock(); } }
+ private:
+ Mutex *const mu_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe);
+};
+
+#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
+template<typename T>
+class ThreadLocalStorage {
+ public:
+ ThreadLocalStorage() {
+ pthread_key_create(&key_, &ThreadLocalStorage::Delete);
+ }
+ ~ThreadLocalStorage() {
+ pthread_key_delete(key_);
+ }
+ T* Get() {
+ T* result = static_cast<T*>(pthread_getspecific(key_));
+ if (result == NULL) {
+ result = new T();
+ pthread_setspecific(key_, result);
+ }
+ return result;
+ }
+ private:
+ static void Delete(void* value) {
+ delete static_cast<T*>(value);
+ }
+ pthread_key_t key_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadLocalStorage);
+};
+#endif
+
+} // namespace internal
+
+// We made these internal so that they would show up as such in the docs,
+// but we don't want to stick "internal::" in front of them everywhere.
+using internal::Mutex;
+using internal::MutexLock;
+using internal::ReaderMutexLock;
+using internal::WriterMutexLock;
+using internal::MutexLockMaybe;
+
+
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_MUTEX_H_
diff --git a/src/google/protobuf/stubs/once.h b/src/google/protobuf/stubs/once.h
index cc62bbaa..1f082c37 100644
--- a/src/google/protobuf/stubs/once.h
+++ b/src/google/protobuf/stubs/once.h
@@ -79,6 +79,7 @@
#define GOOGLE_PROTOBUF_STUBS_ONCE_H__
#include <google/protobuf/stubs/atomicops.h>
+#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
namespace google {
diff --git a/src/google/protobuf/stubs/platform_macros.h b/src/google/protobuf/stubs/platform_macros.h
index 1ff09b83..9e0344d8 100644
--- a/src/google/protobuf/stubs/platform_macros.h
+++ b/src/google/protobuf/stubs/platform_macros.h
@@ -31,8 +31,6 @@
#ifndef GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
#define GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
-#include <google/protobuf/stubs/common.h>
-
#define GOOGLE_PROTOBUF_PLATFORM_ERROR \
#error "Host platform was not detected as supported by protobuf"
@@ -95,14 +93,28 @@ GOOGLE_PROTOBUF_PLATFORM_ERROR
#if defined(__APPLE__)
#define GOOGLE_PROTOBUF_OS_APPLE
+#include <TargetConditionals.h>
+#if TARGET_OS_IPHONE
+#define GOOGLE_PROTOBUF_OS_IPHONE
+#endif
#elif defined(__native_client__)
#define GOOGLE_PROTOBUF_OS_NACL
#elif defined(sun)
#define GOOGLE_PROTOBUF_OS_SOLARIS
#elif defined(_AIX)
#define GOOGLE_PROTOBUF_OS_AIX
+#elif defined(__ANDROID__)
+#define GOOGLE_PROTOBUF_OS_ANDROID
#endif
#undef GOOGLE_PROTOBUF_PLATFORM_ERROR
+#if defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
+// Android ndk does not support the __thread keyword very well yet. Here
+// we use pthread_key_create()/pthread_getspecific()/... methods for
+// TLS support on android.
+// iOS also does not support the __thread keyword.
+#define GOOGLE_PROTOBUF_NO_THREADLOCAL
+#endif
+
#endif // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
diff --git a/src/google/protobuf/stubs/port.h b/src/google/protobuf/stubs/port.h
new file mode 100644
index 00000000..8a5d1a13
--- /dev/null
+++ b/src/google/protobuf/stubs/port.h
@@ -0,0 +1,382 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_STUBS_PORT_H_
+#define GOOGLE_PROTOBUF_STUBS_PORT_H_
+
+#include <assert.h>
+#include <stdlib.h>
+#include <cstddef>
+#include <string>
+#include <string.h>
+#if defined(__osf__)
+// Tru64 lacks stdint.h, but has inttypes.h which defines a superset of
+// what stdint.h would define.
+#include <inttypes.h>
+#elif !defined(_MSC_VER)
+#include <stdint.h>
+#endif
+
+#undef PROTOBUF_LITTLE_ENDIAN
+#ifdef _MSC_VER
+ // Assuming windows is always little-endian.
+ #if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
+ #define PROTOBUF_LITTLE_ENDIAN 1
+ #endif
+ #if _MSC_VER >= 1300
+ // If MSVC has "/RTCc" set, it will complain about truncating casts at
+ // runtime. This file contains some intentional truncating casts.
+ #pragma runtime_checks("c", off)
+ #endif
+#else
+ #include <sys/param.h> // __BYTE_ORDER
+ #if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \
+ (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN)) && \
+ !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
+ #define PROTOBUF_LITTLE_ENDIAN 1
+ #endif
+#endif
+#if defined(_MSC_VER) && defined(PROTOBUF_USE_DLLS)
+ #ifdef LIBPROTOBUF_EXPORTS
+ #define LIBPROTOBUF_EXPORT __declspec(dllexport)
+ #else
+ #define LIBPROTOBUF_EXPORT __declspec(dllimport)
+ #endif
+ #ifdef LIBPROTOC_EXPORTS
+ #define LIBPROTOC_EXPORT __declspec(dllexport)
+ #else
+ #define LIBPROTOC_EXPORT __declspec(dllimport)
+ #endif
+#else
+ #define LIBPROTOBUF_EXPORT
+ #define LIBPROTOC_EXPORT
+#endif
+
+// ===================================================================
+// from google3/base/port.h
+namespace google {
+namespace protobuf {
+
+typedef unsigned int uint;
+
+#ifdef _MSC_VER
+typedef signed __int8 int8;
+typedef __int16 int16;
+typedef __int32 int32;
+typedef __int64 int64;
+
+typedef unsigned __int8 uint8;
+typedef unsigned __int16 uint16;
+typedef unsigned __int32 uint32;
+typedef unsigned __int64 uint64;
+#else
+typedef signed char int8;
+typedef short int16;
+typedef int int32;
+// NOTE: This should be "long long" for consistency with upstream, but
+// something is stacked against this particular type for 64bit hashing.
+// Switching it causes an obvious missing hash function (with an unobvious
+// cause) when building the tests.
+typedef int64_t int64;
+
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+// NOTE: This should be "unsigned long long" for consistency with upstream, but
+// something is stacked against this particular type for 64bit hashing.
+// Switching it causes an obvious missing hash function (with an unobvious
+// cause) when building the tests.
+typedef uint64_t uint64;
+#endif
+
+// long long macros to be used because gcc and vc++ use different suffixes,
+// and different size specifiers in format strings
+#undef GOOGLE_LONGLONG
+#undef GOOGLE_ULONGLONG
+#undef GOOGLE_LL_FORMAT
+
+#ifdef _MSC_VER
+#define GOOGLE_LONGLONG(x) x##I64
+#define GOOGLE_ULONGLONG(x) x##UI64
+#define GOOGLE_LL_FORMAT "I64" // As in printf("%I64d", ...)
+#else
+#define GOOGLE_LONGLONG(x) x##LL
+#define GOOGLE_ULONGLONG(x) x##ULL
+#define GOOGLE_LL_FORMAT "ll" // As in "%lld". Note that "q" is poor form also.
+#endif
+
+static const int32 kint32max = 0x7FFFFFFF;
+static const int32 kint32min = -kint32max - 1;
+static const int64 kint64max = GOOGLE_LONGLONG(0x7FFFFFFFFFFFFFFF);
+static const int64 kint64min = -kint64max - 1;
+static const uint32 kuint32max = 0xFFFFFFFFu;
+static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF);
+
+// -------------------------------------------------------------------
+// Annotations: Some parts of the code have been annotated in ways that might
+// be useful to some compilers or tools, but are not supported universally.
+// You can #define these annotations yourself if the default implementation
+// is not right for you.
+
+#ifndef GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+// For functions we want to force inline.
+// Introduced in gcc 3.1.
+#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline))
+#else
+// Other compilers will have to figure it out for themselves.
+#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+#endif
+#endif
+
+#ifndef GOOGLE_ATTRIBUTE_NOINLINE
+#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+// For functions we want to force not inline.
+// Introduced in gcc 3.1.
+#define GOOGLE_ATTRIBUTE_NOINLINE __attribute__ ((noinline))
+#else
+// Other compilers will have to figure it out for themselves.
+#define GOOGLE_ATTRIBUTE_NOINLINE
+#endif
+#endif
+
+#ifndef GOOGLE_ATTRIBUTE_DEPRECATED
+#ifdef __GNUC__
+// If the method/variable/type is used anywhere, produce a warning.
+#define GOOGLE_ATTRIBUTE_DEPRECATED __attribute__((deprecated))
+#else
+#define GOOGLE_ATTRIBUTE_DEPRECATED
+#endif
+#endif
+
+#ifndef GOOGLE_PREDICT_TRUE
+#ifdef __GNUC__
+// Provided at least since GCC 3.0.
+#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
+#else
+#define GOOGLE_PREDICT_TRUE
+#endif
+#endif
+
+#ifndef GOOGLE_PREDICT_FALSE
+#ifdef __GNUC__
+// Provided at least since GCC 3.0.
+#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0))
+#else
+#define GOOGLE_PREDICT_FALSE
+#endif
+#endif
+
+// Delimits a block of code which may write to memory which is simultaneously
+// written by other threads, but which has been determined to be thread-safe
+// (e.g. because it is an idempotent write).
+#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN
+#define GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN()
+#endif
+#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_END
+#define GOOGLE_SAFE_CONCURRENT_WRITES_END()
+#endif
+
+#if defined(__clang__) && defined(__has_cpp_attribute) \
+ && !defined(GOOGLE_PROTOBUF_OS_APPLE)
+# if defined(GOOGLE_PROTOBUF_OS_NACL) || defined(EMSCRIPTEN) || \
+ __has_cpp_attribute(clang::fallthrough)
+# define GOOGLE_FALLTHROUGH_INTENDED [[clang::fallthrough]]
+# endif
+#endif
+
+#ifndef GOOGLE_FALLTHROUGH_INTENDED
+# define GOOGLE_FALLTHROUGH_INTENDED
+#endif
+
+#define GOOGLE_GUARDED_BY(x)
+#define GOOGLE_ATTRIBUTE_COLD
+
+// x86 and x86-64 can perform unaligned loads/stores directly.
+#if defined(_M_X64) || defined(__x86_64__) || \
+ defined(_M_IX86) || defined(__i386__)
+
+#define GOOGLE_UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
+#define GOOGLE_UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
+#define GOOGLE_UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64 *>(_p))
+
+#define GOOGLE_UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
+#define GOOGLE_UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
+#define GOOGLE_UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64 *>(_p) = (_val))
+
+#else
+inline uint16 GOOGLE_UNALIGNED_LOAD16(const void *p) {
+ uint16 t;
+ memcpy(&t, p, sizeof t);
+ return t;
+}
+
+inline uint32 GOOGLE_UNALIGNED_LOAD32(const void *p) {
+ uint32 t;
+ memcpy(&t, p, sizeof t);
+ return t;
+}
+
+inline uint64 GOOGLE_UNALIGNED_LOAD64(const void *p) {
+ uint64 t;
+ memcpy(&t, p, sizeof t);
+ return t;
+}
+
+inline void GOOGLE_UNALIGNED_STORE16(void *p, uint16 v) {
+ memcpy(p, &v, sizeof v);
+}
+
+inline void GOOGLE_UNALIGNED_STORE32(void *p, uint32 v) {
+ memcpy(p, &v, sizeof v);
+}
+
+inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) {
+ memcpy(p, &v, sizeof v);
+}
+#endif
+
+#if defined(_MSC_VER)
+#define GOOGLE_THREAD_LOCAL __declspec(thread)
+#else
+#define GOOGLE_THREAD_LOCAL __thread
+#endif
+
+// The following guarantees declaration of the byte swap functions, and
+// defines __BYTE_ORDER for MSVC
+#ifdef _MSC_VER
+#include <stdlib.h> // NOLINT(build/include)
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#define bswap_16(x) _byteswap_ushort(x)
+#define bswap_32(x) _byteswap_ulong(x)
+#define bswap_64(x) _byteswap_uint64(x)
+
+#elif defined(__APPLE__)
+// Mac OS X / Darwin features
+#include <libkern/OSByteOrder.h>
+#define bswap_16(x) OSSwapInt16(x)
+#define bswap_32(x) OSSwapInt32(x)
+#define bswap_64(x) OSSwapInt64(x)
+
+#elif defined(__GLIBC__) || defined(__CYGWIN__)
+#include <byteswap.h> // IWYU pragma: export
+
+#else
+
+static inline uint16 bswap_16(uint16 x) {
+ return static_cast<uint16>(((x & 0xFF) << 8) | ((x & 0xFF00) >> 8));
+}
+#define bswap_16(x) bswap_16(x)
+static inline uint32 bswap_32(uint32 x) {
+ return (((x & 0xFF) << 24) |
+ ((x & 0xFF00) << 8) |
+ ((x & 0xFF0000) >> 8) |
+ ((x & 0xFF000000) >> 24));
+}
+#define bswap_32(x) bswap_32(x)
+static inline uint64 bswap_64(uint64 x) {
+ return (((x & GOOGLE_ULONGLONG(0xFF)) << 56) |
+ ((x & GOOGLE_ULONGLONG(0xFF00)) << 40) |
+ ((x & GOOGLE_ULONGLONG(0xFF0000)) << 24) |
+ ((x & GOOGLE_ULONGLONG(0xFF000000)) << 8) |
+ ((x & GOOGLE_ULONGLONG(0xFF00000000)) >> 8) |
+ ((x & GOOGLE_ULONGLONG(0xFF0000000000)) >> 24) |
+ ((x & GOOGLE_ULONGLONG(0xFF000000000000)) >> 40) |
+ ((x & GOOGLE_ULONGLONG(0xFF00000000000000)) >> 56));
+}
+#define bswap_64(x) bswap_64(x)
+
+#endif
+
+// ===================================================================
+// from google3/util/endian/endian.h
+LIBPROTOBUF_EXPORT uint32 ghtonl(uint32 x);
+
+class BigEndian {
+ public:
+#ifdef PROTOBUF_LITTLE_ENDIAN
+
+ static uint16 FromHost16(uint16 x) { return bswap_16(x); }
+ static uint16 ToHost16(uint16 x) { return bswap_16(x); }
+
+ static uint32 FromHost32(uint32 x) { return bswap_32(x); }
+ static uint32 ToHost32(uint32 x) { return bswap_32(x); }
+
+ static uint64 FromHost64(uint64 x) { return bswap_64(x); }
+ static uint64 ToHost64(uint64 x) { return bswap_64(x); }
+
+ static bool IsLittleEndian() { return true; }
+
+#else
+
+ static uint16 FromHost16(uint16 x) { return x; }
+ static uint16 ToHost16(uint16 x) { return x; }
+
+ static uint32 FromHost32(uint32 x) { return x; }
+ static uint32 ToHost32(uint32 x) { return x; }
+
+ static uint64 FromHost64(uint64 x) { return x; }
+ static uint64 ToHost64(uint64 x) { return x; }
+
+ static bool IsLittleEndian() { return false; }
+
+#endif /* ENDIAN */
+
+ // Functions to do unaligned loads and stores in big-endian order.
+ static uint16 Load16(const void *p) {
+ return ToHost16(GOOGLE_UNALIGNED_LOAD16(p));
+ }
+
+ static void Store16(void *p, uint16 v) {
+ GOOGLE_UNALIGNED_STORE16(p, FromHost16(v));
+ }
+
+ static uint32 Load32(const void *p) {
+ return ToHost32(GOOGLE_UNALIGNED_LOAD32(p));
+ }
+
+ static void Store32(void *p, uint32 v) {
+ GOOGLE_UNALIGNED_STORE32(p, FromHost32(v));
+ }
+
+ static uint64 Load64(const void *p) {
+ return ToHost64(GOOGLE_UNALIGNED_LOAD64(p));
+ }
+
+ static void Store64(void *p, uint64 v) {
+ GOOGLE_UNALIGNED_STORE64(p, FromHost64(v));
+ }
+};
+
+
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_PORT_H_
diff --git a/src/google/protobuf/stubs/scoped_ptr.h b/src/google/protobuf/stubs/scoped_ptr.h
new file mode 100644
index 00000000..4423c118
--- /dev/null
+++ b/src/google/protobuf/stubs/scoped_ptr.h
@@ -0,0 +1,236 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_STUBS_SCOPED_PTR_H_
+#define GOOGLE_PROTOBUF_STUBS_SCOPED_PTR_H_
+
+#include <google/protobuf/stubs/port.h>
+
+namespace google {
+namespace protobuf {
+
+// ===================================================================
+// from google3/base/scoped_ptr.h
+
+namespace internal {
+
+// This is an implementation designed to match the anticipated future TR2
+// implementation of the scoped_ptr class, and its closely-related brethren,
+// scoped_array, scoped_ptr_malloc, and make_scoped_ptr.
+
+template <class C> class scoped_ptr;
+template <class C> class scoped_array;
+
+// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
+// automatically deletes the pointer it holds (if any).
+// That is, scoped_ptr<T> owns the T object that it points to.
+// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
+//
+// The size of a scoped_ptr is small:
+// sizeof(scoped_ptr<C>) == sizeof(C*)
+template <class C>
+class scoped_ptr {
+ public:
+
+ // The element type
+ typedef C element_type;
+
+ // Constructor. Defaults to initializing with NULL.
+ // There is no way to create an uninitialized scoped_ptr.
+ // The input parameter must be allocated with new.
+ explicit scoped_ptr(C* p = NULL) : ptr_(p) { }
+
+ // Destructor. If there is a C object, delete it.
+ // We don't need to test ptr_ == NULL because C++ does that for us.
+ ~scoped_ptr() {
+ enum { type_must_be_complete = sizeof(C) };
+ delete ptr_;
+ }
+
+ // Reset. Deletes the current owned object, if any.
+ // Then takes ownership of a new object, if given.
+ // this->reset(this->get()) works.
+ void reset(C* p = NULL) {
+ if (p != ptr_) {
+ enum { type_must_be_complete = sizeof(C) };
+ delete ptr_;
+ ptr_ = p;
+ }
+ }
+
+ // Accessors to get the owned object.
+ // operator* and operator-> will assert() if there is no current object.
+ C& operator*() const {
+ assert(ptr_ != NULL);
+ return *ptr_;
+ }
+ C* operator->() const {
+ assert(ptr_ != NULL);
+ return ptr_;
+ }
+ C* get() const { return ptr_; }
+
+ // Comparison operators.
+ // These return whether two scoped_ptr refer to the same object, not just to
+ // two different but equal objects.
+ bool operator==(C* p) const { return ptr_ == p; }
+ bool operator!=(C* p) const { return ptr_ != p; }
+
+ // Swap two scoped pointers.
+ void swap(scoped_ptr& p2) {
+ C* tmp = ptr_;
+ ptr_ = p2.ptr_;
+ p2.ptr_ = tmp;
+ }
+
+ // Release a pointer.
+ // The return value is the current pointer held by this object.
+ // If this object holds a NULL pointer, the return value is NULL.
+ // After this operation, this object will hold a NULL pointer,
+ // and will not own the object any more.
+ C* release() {
+ C* retVal = ptr_;
+ ptr_ = NULL;
+ return retVal;
+ }
+
+ private:
+ C* ptr_;
+
+ // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't
+ // make sense, and if C2 == C, it still doesn't make sense because you should
+ // never have the same object owned by two different scoped_ptrs.
+ template <class C2> bool operator==(scoped_ptr<C2> const& p2) const;
+ template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const;
+
+ // Disallow evil constructors
+ scoped_ptr(const scoped_ptr&);
+ void operator=(const scoped_ptr&);
+};
+
+// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
+// with new [] and the destructor deletes objects with delete [].
+//
+// As with scoped_ptr<C>, a scoped_array<C> either points to an object
+// or is NULL. A scoped_array<C> owns the object that it points to.
+//
+// Size: sizeof(scoped_array<C>) == sizeof(C*)
+template <class C>
+class scoped_array {
+ public:
+
+ // The element type
+ typedef C element_type;
+
+ // Constructor. Defaults to initializing with NULL.
+ // There is no way to create an uninitialized scoped_array.
+ // The input parameter must be allocated with new [].
+ explicit scoped_array(C* p = NULL) : array_(p) { }
+
+ // Destructor. If there is a C object, delete it.
+ // We don't need to test ptr_ == NULL because C++ does that for us.
+ ~scoped_array() {
+ enum { type_must_be_complete = sizeof(C) };
+ delete[] array_;
+ }
+
+ // Reset. Deletes the current owned object, if any.
+ // Then takes ownership of a new object, if given.
+ // this->reset(this->get()) works.
+ void reset(C* p = NULL) {
+ if (p != array_) {
+ enum { type_must_be_complete = sizeof(C) };
+ delete[] array_;
+ array_ = p;
+ }
+ }
+
+ // Get one element of the current object.
+ // Will assert() if there is no current object, or index i is negative.
+ C& operator[](std::ptrdiff_t i) const {
+ assert(i >= 0);
+ assert(array_ != NULL);
+ return array_[i];
+ }
+
+ // Get a pointer to the zeroth element of the current object.
+ // If there is no current object, return NULL.
+ C* get() const {
+ return array_;
+ }
+
+ // Comparison operators.
+ // These return whether two scoped_array refer to the same object, not just to
+ // two different but equal objects.
+ bool operator==(C* p) const { return array_ == p; }
+ bool operator!=(C* p) const { return array_ != p; }
+
+ // Swap two scoped arrays.
+ void swap(scoped_array& p2) {
+ C* tmp = array_;
+ array_ = p2.array_;
+ p2.array_ = tmp;
+ }
+
+ // Release an array.
+ // The return value is the current pointer held by this object.
+ // If this object holds a NULL pointer, the return value is NULL.
+ // After this operation, this object will hold a NULL pointer,
+ // and will not own the object any more.
+ C* release() {
+ C* retVal = array_;
+ array_ = NULL;
+ return retVal;
+ }
+
+ private:
+ C* array_;
+
+ // Forbid comparison of different scoped_array types.
+ template <class C2> bool operator==(scoped_array<C2> const& p2) const;
+ template <class C2> bool operator!=(scoped_array<C2> const& p2) const;
+
+ // Disallow evil constructors
+ scoped_array(const scoped_array&);
+ void operator=(const scoped_array&);
+};
+
+} // namespace internal
+
+// We made these internal so that they would show up as such in the docs,
+// but we don't want to stick "internal::" in front of them everywhere.
+using internal::scoped_ptr;
+using internal::scoped_array;
+
+
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_SCOPED_PTR_H_
diff --git a/src/google/protobuf/stubs/singleton.h b/src/google/protobuf/stubs/singleton.h
index e123e4fe..9301f549 100644
--- a/src/google/protobuf/stubs/singleton.h
+++ b/src/google/protobuf/stubs/singleton.h
@@ -44,6 +44,10 @@ class Singleton {
GoogleOnceInit(&once_, &Singleton<T>::Init);
return instance_;
}
+ static void ShutDown() {
+ delete instance_;
+ instance_ = NULL;
+ }
private:
static void Init() {
instance_ = new T();
@@ -56,7 +60,7 @@ template<typename T>
ProtobufOnceType Singleton<T>::once_;
template<typename T>
-T* Singleton<T>::instance_;
+T* Singleton<T>::instance_ = NULL;
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/stubs/status.cc b/src/google/protobuf/stubs/status.cc
new file mode 100644
index 00000000..7314c563
--- /dev/null
+++ b/src/google/protobuf/stubs/status.cc
@@ -0,0 +1,135 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include <google/protobuf/stubs/status.h>
+
+#include <ostream>
+#include <stdint.h>
+#include <stdio.h>
+#include <string>
+#include <utility>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace error {
+inline string CodeEnumToString(error::Code code) {
+ switch (code) {
+ case OK:
+ return "OK";
+ case CANCELLED:
+ return "CANCELLED";
+ case UNKNOWN:
+ return "UNKNOWN";
+ case INVALID_ARGUMENT:
+ return "INVALID_ARGUMENT";
+ case DEADLINE_EXCEEDED:
+ return "DEADLINE_EXCEEDED";
+ case NOT_FOUND:
+ return "NOT_FOUND";
+ case ALREADY_EXISTS:
+ return "ALREADY_EXISTS";
+ case PERMISSION_DENIED:
+ return "PERMISSION_DENIED";
+ case UNAUTHENTICATED:
+ return "UNAUTHENTICATED";
+ case RESOURCE_EXHAUSTED:
+ return "RESOURCE_EXHAUSTED";
+ case FAILED_PRECONDITION:
+ return "FAILED_PRECONDITION";
+ case ABORTED:
+ return "ABORTED";
+ case OUT_OF_RANGE:
+ return "OUT_OF_RANGE";
+ case UNIMPLEMENTED:
+ return "UNIMPLEMENTED";
+ case INTERNAL:
+ return "INTERNAL";
+ case UNAVAILABLE:
+ return "UNAVAILABLE";
+ case DATA_LOSS:
+ return "DATA_LOSS";
+ }
+
+ // No default clause, clang will abort if a code is missing from
+ // above switch.
+ return "UNKNOWN";
+}
+} // namespace error.
+
+const Status Status::OK = Status();
+const Status Status::CANCELLED = Status(error::CANCELLED, "");
+const Status Status::UNKNOWN = Status(error::UNKNOWN, "");
+
+Status::Status() : error_code_(error::OK) {
+}
+
+Status::Status(error::Code error_code, StringPiece error_message)
+ : error_code_(error_code) {
+ if (error_code != error::OK) {
+ error_message_ = error_message.ToString();
+ }
+}
+
+Status::Status(const Status& other)
+ : error_code_(other.error_code_), error_message_(other.error_message_) {
+}
+
+Status& Status::operator=(const Status& other) {
+ error_code_ = other.error_code_;
+ error_message_ = other.error_message_;
+ return *this;
+}
+
+bool Status::operator==(const Status& x) const {
+ return error_code_ == x.error_code_ &&
+ error_message_ == x.error_message_;
+}
+
+string Status::ToString() const {
+ if (error_code_ == error::OK) {
+ return "OK";
+ } else {
+ if (error_message_.empty()) {
+ return error::CodeEnumToString(error_code_);
+ } else {
+ return error::CodeEnumToString(error_code_) + ":" +
+ error_message_;
+ }
+ }
+}
+
+ostream& operator<<(ostream& os, const Status& x) {
+ os << x.ToString();
+ return os;
+}
+
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/status.h b/src/google/protobuf/stubs/status.h
new file mode 100644
index 00000000..614ab994
--- /dev/null
+++ b/src/google/protobuf/stubs/status.h
@@ -0,0 +1,116 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifndef GOOGLE_PROTOBUF_STUBS_STATUS_H_
+#define GOOGLE_PROTOBUF_STUBS_STATUS_H_
+
+#include <iosfwd>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace error {
+// These values must match error codes defined in google/rpc/code.proto.
+enum Code {
+ OK = 0,
+ CANCELLED = 1,
+ UNKNOWN = 2,
+ INVALID_ARGUMENT = 3,
+ DEADLINE_EXCEEDED = 4,
+ NOT_FOUND = 5,
+ ALREADY_EXISTS = 6,
+ PERMISSION_DENIED = 7,
+ UNAUTHENTICATED = 16,
+ RESOURCE_EXHAUSTED = 8,
+ FAILED_PRECONDITION = 9,
+ ABORTED = 10,
+ OUT_OF_RANGE = 11,
+ UNIMPLEMENTED = 12,
+ INTERNAL = 13,
+ UNAVAILABLE = 14,
+ DATA_LOSS = 15,
+};
+} // namespace error
+
+class LIBPROTOBUF_EXPORT Status {
+ public:
+ // Creates a "successful" status.
+ Status();
+
+ // Create a status in the canonical error space with the specified
+ // code, and error message. If "code == 0", error_message is
+ // ignored and a Status object identical to Status::OK is
+ // constructed.
+ Status(error::Code error_code, StringPiece error_message);
+ Status(const Status&);
+ Status& operator=(const Status& x);
+ ~Status() {}
+
+ // Some pre-defined Status objects
+ static const Status OK; // Identical to 0-arg constructor
+ static const Status CANCELLED;
+ static const Status UNKNOWN;
+
+ // Accessor
+ bool ok() const {
+ return error_code_ == error::OK;
+ }
+ int error_code() const {
+ return error_code_;
+ }
+ StringPiece error_message() const {
+ return error_message_;
+ }
+
+ bool operator==(const Status& x) const;
+ bool operator!=(const Status& x) const {
+ return !operator==(x);
+ }
+
+ // Return a combination of the error code name and message.
+ string ToString() const;
+
+ private:
+ error::Code error_code_;
+ string error_message_;
+};
+
+// Prints a human-readable representation of 'x' to 'os'.
+LIBPROTOBUF_EXPORT ostream& operator<<(ostream& os, const Status& x);
+
+#define EXPECT_OK(value) EXPECT_TRUE((value).ok())
+
+} // namespace util
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_
diff --git a/src/google/protobuf/stubs/status_macros.h b/src/google/protobuf/stubs/status_macros.h
new file mode 100644
index 00000000..743e79a7
--- /dev/null
+++ b/src/google/protobuf/stubs/status_macros.h
@@ -0,0 +1,89 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// From: util/task/contrib/status_macros/status_macros.h
+
+#ifndef GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_
+#define GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/statusor.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+// Run a command that returns a util::Status. If the called code returns an
+// error status, return that status up out of this method too.
+//
+// Example:
+// RETURN_IF_ERROR(DoThings(4));
+#define RETURN_IF_ERROR(expr) \
+ do { \
+ /* Using _status below to avoid capture problems if expr is "status". */ \
+ const ::google::protobuf::util::Status _status = (expr); \
+ if (GOOGLE_PREDICT_FALSE(!_status.ok())) return _status; \
+ } while (0)
+
+// Internal helper for concatenating macro values.
+#define STATUS_MACROS_CONCAT_NAME_INNER(x, y) x##y
+#define STATUS_MACROS_CONCAT_NAME(x, y) STATUS_MACROS_CONCAT_NAME_INNER(x, y)
+
+template<typename T>
+Status DoAssignOrReturn(T& lhs, StatusOr<T> result) {
+ if (result.ok()) {
+ lhs = result.ValueOrDie();
+ }
+ return result.status();
+}
+
+#define ASSIGN_OR_RETURN_IMPL(status, lhs, rexpr) \
+ Status status = DoAssignOrReturn(lhs, (rexpr)); \
+ if (GOOGLE_PREDICT_FALSE(!status.ok())) return status;
+
+// Executes an expression that returns a util::StatusOr, extracting its value
+// into the variable defined by lhs (or returning on error).
+//
+// Example: Assigning to an existing value
+// ValueType value;
+// ASSIGN_OR_RETURN(value, MaybeGetValue(arg));
+//
+// WARNING: ASSIGN_OR_RETURN expands into multiple statements; it cannot be used
+// in a single statement (e.g. as the body of an if statement without {})!
+#define ASSIGN_OR_RETURN(lhs, rexpr) \
+ ASSIGN_OR_RETURN_IMPL( \
+ STATUS_MACROS_CONCAT_NAME(_status_or_value, __COUNTER__), lhs, rexpr);
+
+} // namespace util
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_
diff --git a/src/google/protobuf/stubs/status_test.cc b/src/google/protobuf/stubs/status_test.cc
new file mode 100644
index 00000000..c70c33c4
--- /dev/null
+++ b/src/google/protobuf/stubs/status_test.cc
@@ -0,0 +1,131 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include <google/protobuf/stubs/status.h>
+
+#include <stdio.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+TEST(Status, Empty) {
+ util::Status status;
+ EXPECT_EQ(util::error::OK, util::Status::OK.error_code());
+ EXPECT_EQ("OK", util::Status::OK.ToString());
+}
+
+TEST(Status, GenericCodes) {
+ EXPECT_EQ(util::error::OK, util::Status::OK.error_code());
+ EXPECT_EQ(util::error::CANCELLED, util::Status::CANCELLED.error_code());
+ EXPECT_EQ(util::error::UNKNOWN, util::Status::UNKNOWN.error_code());
+}
+
+TEST(Status, ConstructorZero) {
+ util::Status status(util::error::OK, "msg");
+ EXPECT_TRUE(status.ok());
+ EXPECT_EQ("OK", status.ToString());
+}
+
+TEST(Status, CheckOK) {
+ util::Status status;
+ GOOGLE_CHECK_OK(status);
+ GOOGLE_CHECK_OK(status) << "Failed";
+ GOOGLE_DCHECK_OK(status) << "Failed";
+}
+
+TEST(Status, ErrorMessage) {
+ util::Status status(util::error::INVALID_ARGUMENT, "");
+ EXPECT_FALSE(status.ok());
+ EXPECT_EQ("", status.error_message().ToString());
+ EXPECT_EQ("INVALID_ARGUMENT", status.ToString());
+ status = util::Status(util::error::INVALID_ARGUMENT, "msg");
+ EXPECT_FALSE(status.ok());
+ EXPECT_EQ("msg", status.error_message().ToString());
+ EXPECT_EQ("INVALID_ARGUMENT:msg", status.ToString());
+ status = util::Status(util::error::OK, "msg");
+ EXPECT_TRUE(status.ok());
+ EXPECT_EQ("", status.error_message().ToString());
+ EXPECT_EQ("OK", status.ToString());
+}
+
+TEST(Status, Copy) {
+ util::Status a(util::error::UNKNOWN, "message");
+ util::Status b(a);
+ ASSERT_EQ(a.ToString(), b.ToString());
+}
+
+TEST(Status, Assign) {
+ util::Status a(util::error::UNKNOWN, "message");
+ util::Status b;
+ b = a;
+ ASSERT_EQ(a.ToString(), b.ToString());
+}
+
+TEST(Status, AssignEmpty) {
+ util::Status a(util::error::UNKNOWN, "message");
+ util::Status b;
+ a = b;
+ ASSERT_EQ(string("OK"), a.ToString());
+ ASSERT_TRUE(b.ok());
+ ASSERT_TRUE(a.ok());
+}
+
+TEST(Status, EqualsOK) {
+ ASSERT_EQ(util::Status::OK, util::Status());
+}
+
+TEST(Status, EqualsSame) {
+ const util::Status a = util::Status(util::error::CANCELLED, "message");
+ const util::Status b = util::Status(util::error::CANCELLED, "message");
+ ASSERT_EQ(a, b);
+}
+
+TEST(Status, EqualsCopy) {
+ const util::Status a = util::Status(util::error::CANCELLED, "message");
+ const util::Status b = a;
+ ASSERT_EQ(a, b);
+}
+
+TEST(Status, EqualsDifferentCode) {
+ const util::Status a = util::Status(util::error::CANCELLED, "message");
+ const util::Status b = util::Status(util::error::UNKNOWN, "message");
+ ASSERT_NE(a, b);
+}
+
+TEST(Status, EqualsDifferentMessage) {
+ const util::Status a = util::Status(util::error::CANCELLED, "message");
+ const util::Status b = util::Status(util::error::CANCELLED, "another");
+ ASSERT_NE(a, b);
+}
+} // namespace
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/statusor.cc b/src/google/protobuf/stubs/statusor.cc
new file mode 100644
index 00000000..48d1402a
--- /dev/null
+++ b/src/google/protobuf/stubs/statusor.cc
@@ -0,0 +1,46 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/stubs/statusor.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace internal {
+
+void StatusOrHelper::Crash(const Status& status) {
+ GOOGLE_LOG(FATAL) << "Attempting to fetch value instead of handling error "
+ << status.ToString();
+}
+
+} // namespace internal
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/statusor.h b/src/google/protobuf/stubs/statusor.h
new file mode 100644
index 00000000..a9d2b374
--- /dev/null
+++ b/src/google/protobuf/stubs/statusor.h
@@ -0,0 +1,259 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// StatusOr<T> is the union of a Status object and a T
+// object. StatusOr models the concept of an object that is either a
+// usable value, or an error Status explaining why such a value is
+// not present. To this end, StatusOr<T> does not allow its Status
+// value to be Status::OK. Further, StatusOr<T*> does not allow the
+// contained pointer to be NULL.
+//
+// The primary use-case for StatusOr<T> is as the return value of a
+// function which may fail.
+//
+// Example client usage for a StatusOr<T>, where T is not a pointer:
+//
+// StatusOr<float> result = DoBigCalculationThatCouldFail();
+// if (result.ok()) {
+// float answer = result.ValueOrDie();
+// printf("Big calculation yielded: %f", answer);
+// } else {
+// LOG(ERROR) << result.status();
+// }
+//
+// Example client usage for a StatusOr<T*>:
+//
+// StatusOr<Foo*> result = FooFactory::MakeNewFoo(arg);
+// if (result.ok()) {
+// std::unique_ptr<Foo> foo(result.ValueOrDie());
+// foo->DoSomethingCool();
+// } else {
+// LOG(ERROR) << result.status();
+// }
+//
+// Example client usage for a StatusOr<std::unique_ptr<T>>:
+//
+// StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
+// if (result.ok()) {
+// std::unique_ptr<Foo> foo = result.ConsumeValueOrDie();
+// foo->DoSomethingCool();
+// } else {
+// LOG(ERROR) << result.status();
+// }
+//
+// Example factory implementation returning StatusOr<T*>:
+//
+// StatusOr<Foo*> FooFactory::MakeNewFoo(int arg) {
+// if (arg <= 0) {
+// return ::util::Status(::util::error::INVALID_ARGUMENT,
+// "Arg must be positive");
+// } else {
+// return new Foo(arg);
+// }
+// }
+//
+
+#ifndef GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
+#define GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
+
+#include <new>
+#include <string>
+#include <utility>
+
+#include <google/protobuf/stubs/status.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+template<typename T>
+class StatusOr {
+ template<typename U> friend class StatusOr;
+
+ public:
+ // Construct a new StatusOr with Status::UNKNOWN status
+ StatusOr();
+
+ // Construct a new StatusOr with the given non-ok status. After calling
+ // this constructor, calls to ValueOrDie() will CHECK-fail.
+ //
+ // NOTE: Not explicit - we want to use StatusOr<T> as a return
+ // value, so it is convenient and sensible to be able to do 'return
+ // Status()' when the return type is StatusOr<T>.
+ //
+ // REQUIRES: status != Status::OK. This requirement is DCHECKed.
+ // In optimized builds, passing Status::OK here will have the effect
+ // of passing PosixErrorSpace::EINVAL as a fallback.
+ StatusOr(const Status& status); // NOLINT
+
+ // Construct a new StatusOr with the given value. If T is a plain pointer,
+ // value must not be NULL. After calling this constructor, calls to
+ // ValueOrDie() will succeed, and calls to status() will return OK.
+ //
+ // NOTE: Not explicit - we want to use StatusOr<T> as a return type
+ // so it is convenient and sensible to be able to do 'return T()'
+ // when when the return type is StatusOr<T>.
+ //
+ // REQUIRES: if T is a plain pointer, value != NULL. This requirement is
+ // DCHECKed. In optimized builds, passing a NULL pointer here will have
+ // the effect of passing PosixErrorSpace::EINVAL as a fallback.
+ StatusOr(const T& value); // NOLINT
+
+ // Copy constructor.
+ StatusOr(const StatusOr& other);
+
+ // Conversion copy constructor, T must be copy constructible from U
+ template<typename U>
+ StatusOr(const StatusOr<U>& other);
+
+ // Assignment operator.
+ StatusOr& operator=(const StatusOr& other);
+
+ // Conversion assignment operator, T must be assignable from U
+ template<typename U>
+ StatusOr& operator=(const StatusOr<U>& other);
+
+ // Returns a reference to our status. If this contains a T, then
+ // returns Status::OK.
+ const Status& status() const;
+
+ // Returns this->status().ok()
+ bool ok() const;
+
+ // Returns a reference to our current value, or CHECK-fails if !this->ok().
+ // If you need to initialize a T object from the stored value,
+ // ConsumeValueOrDie() may be more efficient.
+ const T& ValueOrDie() const;
+
+ private:
+ Status status_;
+ T value_;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Implementation details for StatusOr<T>
+
+namespace internal {
+
+class LIBPROTOBUF_EXPORT StatusOrHelper {
+ public:
+ // Move type-agnostic error handling to the .cc.
+ static void Crash(const util::Status& status);
+
+ // Customized behavior for StatusOr<T> vs. StatusOr<T*>
+ template<typename T>
+ struct Specialize;
+};
+
+template<typename T>
+struct StatusOrHelper::Specialize {
+ // For non-pointer T, a reference can never be NULL.
+ static inline bool IsValueNull(const T& t) { return false; }
+};
+
+template<typename T>
+struct StatusOrHelper::Specialize<T*> {
+ static inline bool IsValueNull(const T* t) { return t == NULL; }
+};
+
+} // namespace internal
+
+template<typename T>
+inline StatusOr<T>::StatusOr()
+ : status_(util::Status::UNKNOWN) {
+}
+
+template<typename T>
+inline StatusOr<T>::StatusOr(const Status& status) {
+ if (status.ok()) {
+ status_ = Status(error::INTERNAL, "Status::OK is not a valid argument.");
+ } else {
+ status_ = status;
+ }
+}
+
+template<typename T>
+inline StatusOr<T>::StatusOr(const T& value) {
+ if (internal::StatusOrHelper::Specialize<T>::IsValueNull(value)) {
+ status_ = Status(error::INTERNAL, "NULL is not a vaild argument.");
+ } else {
+ status_ = Status::OK;
+ value_ = value;
+ }
+}
+
+template<typename T>
+inline StatusOr<T>::StatusOr(const StatusOr<T>& other)
+ : status_(other.status_), value_(other.value_) {
+}
+
+template<typename T>
+inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<T>& other) {
+ status_ = other.status_;
+ value_ = other.value_;
+ return *this;
+}
+
+template<typename T>
+template<typename U>
+inline StatusOr<T>::StatusOr(const StatusOr<U>& other)
+ : status_(other.status_), value_(other.value_) {
+}
+
+template<typename T>
+template<typename U>
+inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<U>& other) {
+ status_ = other.status_;
+ value_ = other.value_;
+ return *this;
+}
+
+template<typename T>
+inline const Status& StatusOr<T>::status() const {
+ return status_;
+}
+
+template<typename T>
+inline bool StatusOr<T>::ok() const {
+ return status().ok();
+}
+
+template<typename T>
+inline const T& StatusOr<T>::ValueOrDie() const {
+ if (!status_.ok()) {
+ internal::StatusOrHelper::Crash(status_);
+ }
+ return value_;
+}
+} // namespace util
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
diff --git a/src/google/protobuf/stubs/statusor_test.cc b/src/google/protobuf/stubs/statusor_test.cc
new file mode 100644
index 00000000..6e2a9e55
--- /dev/null
+++ b/src/google/protobuf/stubs/statusor_test.cc
@@ -0,0 +1,274 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/stubs/statusor.h>
+
+#include <errno.h>
+#include <memory>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace {
+
+class Base1 {
+ public:
+ virtual ~Base1() {}
+ int pad;
+};
+
+class Base2 {
+ public:
+ virtual ~Base2() {}
+ int yetotherpad;
+};
+
+class Derived : public Base1, public Base2 {
+ public:
+ virtual ~Derived() {}
+ int evenmorepad;
+};
+
+class CopyNoAssign {
+ public:
+ explicit CopyNoAssign(int value) : foo(value) {}
+ CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {}
+ int foo;
+ private:
+ const CopyNoAssign& operator=(const CopyNoAssign&);
+};
+
+TEST(StatusOr, TestDefaultCtor) {
+ StatusOr<int> thing;
+ EXPECT_FALSE(thing.ok());
+ EXPECT_EQ(Status::UNKNOWN, thing.status());
+}
+
+TEST(StatusOr, TestStatusCtor) {
+ StatusOr<int> thing(Status::CANCELLED);
+ EXPECT_FALSE(thing.ok());
+ EXPECT_EQ(Status::CANCELLED, thing.status());
+}
+
+TEST(StatusOr, TestValueCtor) {
+ const int kI = 4;
+ StatusOr<int> thing(kI);
+ EXPECT_TRUE(thing.ok());
+ EXPECT_EQ(kI, thing.ValueOrDie());
+}
+
+TEST(StatusOr, TestCopyCtorStatusOk) {
+ const int kI = 4;
+ StatusOr<int> original(kI);
+ StatusOr<int> copy(original);
+ EXPECT_EQ(original.status(), copy.status());
+ EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
+}
+
+TEST(StatusOr, TestCopyCtorStatusNotOk) {
+ StatusOr<int> original(Status::CANCELLED);
+ StatusOr<int> copy(original);
+ EXPECT_EQ(original.status(), copy.status());
+}
+
+TEST(StatusOr, TestCopyCtorStatusOKConverting) {
+ const int kI = 4;
+ StatusOr<int> original(kI);
+ StatusOr<double> copy(original);
+ EXPECT_EQ(original.status(), copy.status());
+ EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
+}
+
+TEST(StatusOr, TestCopyCtorStatusNotOkConverting) {
+ StatusOr<int> original(Status::CANCELLED);
+ StatusOr<double> copy(original);
+ EXPECT_EQ(original.status(), copy.status());
+}
+
+TEST(StatusOr, TestAssignmentStatusOk) {
+ const int kI = 4;
+ StatusOr<int> source(kI);
+ StatusOr<int> target;
+ target = source;
+ EXPECT_EQ(source.status(), target.status());
+ EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie());
+}
+
+TEST(StatusOr, TestAssignmentStatusNotOk) {
+ StatusOr<int> source(Status::CANCELLED);
+ StatusOr<int> target;
+ target = source;
+ EXPECT_EQ(source.status(), target.status());
+}
+
+TEST(StatusOr, TestAssignmentStatusOKConverting) {
+ const int kI = 4;
+ StatusOr<int> source(kI);
+ StatusOr<double> target;
+ target = source;
+ EXPECT_EQ(source.status(), target.status());
+ EXPECT_DOUBLE_EQ(source.ValueOrDie(), target.ValueOrDie());
+}
+
+TEST(StatusOr, TestAssignmentStatusNotOkConverting) {
+ StatusOr<int> source(Status::CANCELLED);
+ StatusOr<double> target;
+ target = source;
+ EXPECT_EQ(source.status(), target.status());
+}
+
+TEST(StatusOr, TestStatus) {
+ StatusOr<int> good(4);
+ EXPECT_TRUE(good.ok());
+ StatusOr<int> bad(Status::CANCELLED);
+ EXPECT_FALSE(bad.ok());
+ EXPECT_EQ(Status::CANCELLED, bad.status());
+}
+
+TEST(StatusOr, TestValue) {
+ const int kI = 4;
+ StatusOr<int> thing(kI);
+ EXPECT_EQ(kI, thing.ValueOrDie());
+}
+
+TEST(StatusOr, TestValueConst) {
+ const int kI = 4;
+ const StatusOr<int> thing(kI);
+ EXPECT_EQ(kI, thing.ValueOrDie());
+}
+
+TEST(StatusOr, TestPointerDefaultCtor) {
+ StatusOr<int*> thing;
+ EXPECT_FALSE(thing.ok());
+ EXPECT_EQ(Status::UNKNOWN, thing.status());
+}
+
+TEST(StatusOr, TestPointerStatusCtor) {
+ StatusOr<int*> thing(Status::CANCELLED);
+ EXPECT_FALSE(thing.ok());
+ EXPECT_EQ(Status::CANCELLED, thing.status());
+}
+
+TEST(StatusOr, TestPointerValueCtor) {
+ const int kI = 4;
+ StatusOr<const int*> thing(&kI);
+ EXPECT_TRUE(thing.ok());
+ EXPECT_EQ(&kI, thing.ValueOrDie());
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusOk) {
+ const int kI = 0;
+ StatusOr<const int*> original(&kI);
+ StatusOr<const int*> copy(original);
+ EXPECT_EQ(original.status(), copy.status());
+ EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusNotOk) {
+ StatusOr<int*> original(Status::CANCELLED);
+ StatusOr<int*> copy(original);
+ EXPECT_EQ(original.status(), copy.status());
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusOKConverting) {
+ Derived derived;
+ StatusOr<Derived*> original(&derived);
+ StatusOr<Base2*> copy(original);
+ EXPECT_EQ(original.status(), copy.status());
+ EXPECT_EQ(static_cast<const Base2*>(original.ValueOrDie()),
+ copy.ValueOrDie());
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) {
+ StatusOr<Derived*> original(Status::CANCELLED);
+ StatusOr<Base2*> copy(original);
+ EXPECT_EQ(original.status(), copy.status());
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusOk) {
+ const int kI = 0;
+ StatusOr<const int*> source(&kI);
+ StatusOr<const int*> target;
+ target = source;
+ EXPECT_EQ(source.status(), target.status());
+ EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie());
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusNotOk) {
+ StatusOr<int*> source(Status::CANCELLED);
+ StatusOr<int*> target;
+ target = source;
+ EXPECT_EQ(source.status(), target.status());
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusOKConverting) {
+ Derived derived;
+ StatusOr<Derived*> source(&derived);
+ StatusOr<Base2*> target;
+ target = source;
+ EXPECT_EQ(source.status(), target.status());
+ EXPECT_EQ(static_cast<const Base2*>(source.ValueOrDie()),
+ target.ValueOrDie());
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) {
+ StatusOr<Derived*> source(Status::CANCELLED);
+ StatusOr<Base2*> target;
+ target = source;
+ EXPECT_EQ(source.status(), target.status());
+}
+
+TEST(StatusOr, TestPointerStatus) {
+ const int kI = 0;
+ StatusOr<const int*> good(&kI);
+ EXPECT_TRUE(good.ok());
+ StatusOr<const int*> bad(Status::CANCELLED);
+ EXPECT_EQ(Status::CANCELLED, bad.status());
+}
+
+TEST(StatusOr, TestPointerValue) {
+ const int kI = 0;
+ StatusOr<const int*> thing(&kI);
+ EXPECT_EQ(&kI, thing.ValueOrDie());
+}
+
+TEST(StatusOr, TestPointerValueConst) {
+ const int kI = 0;
+ const StatusOr<const int*> thing(&kI);
+ EXPECT_EQ(&kI, thing.ValueOrDie());
+}
+
+} // namespace
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/stringpiece.cc b/src/google/protobuf/stubs/stringpiece.cc
new file mode 100644
index 00000000..989474b7
--- /dev/null
+++ b/src/google/protobuf/stubs/stringpiece.cc
@@ -0,0 +1,268 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include <google/protobuf/stubs/stringpiece.h>
+
+#include <string.h>
+#include <algorithm>
+#include <climits>
+#include <string>
+#include <ostream>
+
+namespace google {
+namespace protobuf {
+std::ostream& operator<<(std::ostream& o, StringPiece piece) {
+ o.write(piece.data(), piece.size());
+ return o;
+}
+
+// Out-of-line error path.
+void StringPiece::LogFatalSizeTooBig(size_t size, const char* details) {
+ GOOGLE_LOG(FATAL) << "size too big: " << size << " details: " << details;
+}
+
+StringPiece::StringPiece(StringPiece x, stringpiece_ssize_type pos)
+ : ptr_(x.ptr_ + pos), length_(x.length_ - pos) {
+ GOOGLE_DCHECK_LE(0, pos);
+ GOOGLE_DCHECK_LE(pos, x.length_);
+}
+
+StringPiece::StringPiece(StringPiece x,
+ stringpiece_ssize_type pos,
+ stringpiece_ssize_type len)
+ : ptr_(x.ptr_ + pos), length_(std::min(len, x.length_ - pos)) {
+ GOOGLE_DCHECK_LE(0, pos);
+ GOOGLE_DCHECK_LE(pos, x.length_);
+ GOOGLE_DCHECK_GE(len, 0);
+}
+
+void StringPiece::CopyToString(string* target) const {
+ target->assign(ptr_, length_);
+}
+
+void StringPiece::AppendToString(string* target) const {
+ target->append(ptr_, length_);
+}
+
+bool StringPiece::Consume(StringPiece x) {
+ if (starts_with(x)) {
+ ptr_ += x.length_;
+ length_ -= x.length_;
+ return true;
+ }
+ return false;
+}
+
+bool StringPiece::ConsumeFromEnd(StringPiece x) {
+ if (ends_with(x)) {
+ length_ -= x.length_;
+ return true;
+ }
+ return false;
+}
+
+stringpiece_ssize_type StringPiece::copy(char* buf,
+ size_type n,
+ size_type pos) const {
+ stringpiece_ssize_type ret = std::min(length_ - pos, n);
+ memcpy(buf, ptr_ + pos, ret);
+ return ret;
+}
+
+bool StringPiece::contains(StringPiece s) const {
+ return find(s, 0) != npos;
+}
+
+stringpiece_ssize_type StringPiece::find(StringPiece s, size_type pos) const {
+ if (length_ <= 0 || pos > static_cast<size_type>(length_)) {
+ if (length_ == 0 && pos == 0 && s.length_ == 0) return 0;
+ return npos;
+ }
+ const char *result = std::search(ptr_ + pos, ptr_ + length_,
+ s.ptr_, s.ptr_ + s.length_);
+ return result == ptr_ + length_ ? npos : result - ptr_;
+}
+
+stringpiece_ssize_type StringPiece::find(char c, size_type pos) const {
+ if (length_ <= 0 || pos >= static_cast<size_type>(length_)) {
+ return npos;
+ }
+ const char* result = static_cast<const char*>(
+ memchr(ptr_ + pos, c, length_ - pos));
+ return result != NULL ? result - ptr_ : npos;
+}
+
+stringpiece_ssize_type StringPiece::rfind(StringPiece s, size_type pos) const {
+ if (length_ < s.length_) return npos;
+ const size_t ulen = length_;
+ if (s.length_ == 0) return std::min(ulen, pos);
+
+ const char* last = ptr_ + std::min(ulen - s.length_, pos) + s.length_;
+ const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_);
+ return result != last ? result - ptr_ : npos;
+}
+
+// Search range is [0..pos] inclusive. If pos == npos, search everything.
+stringpiece_ssize_type StringPiece::rfind(char c, size_type pos) const {
+ // Note: memrchr() is not available on Windows.
+ if (length_ <= 0) return npos;
+ for (stringpiece_ssize_type i =
+ std::min(pos, static_cast<size_type>(length_ - 1));
+ i >= 0; --i) {
+ if (ptr_[i] == c) {
+ return i;
+ }
+ }
+ return npos;
+}
+
+// For each character in characters_wanted, sets the index corresponding
+// to the ASCII code of that character to 1 in table. This is used by
+// the find_.*_of methods below to tell whether or not a character is in
+// the lookup table in constant time.
+// The argument `table' must be an array that is large enough to hold all
+// the possible values of an unsigned char. Thus it should be be declared
+// as follows:
+// bool table[UCHAR_MAX + 1]
+static inline void BuildLookupTable(StringPiece characters_wanted,
+ bool* table) {
+ const stringpiece_ssize_type length = characters_wanted.length();
+ const char* const data = characters_wanted.data();
+ for (stringpiece_ssize_type i = 0; i < length; ++i) {
+ table[static_cast<unsigned char>(data[i])] = true;
+ }
+}
+
+stringpiece_ssize_type StringPiece::find_first_of(StringPiece s,
+ size_type pos) const {
+ if (length_ <= 0 || s.length_ <= 0) {
+ return npos;
+ }
+ // Avoid the cost of BuildLookupTable() for a single-character search.
+ if (s.length_ == 1) return find_first_of(s.ptr_[0], pos);
+
+ bool lookup[UCHAR_MAX + 1] = { false };
+ BuildLookupTable(s, lookup);
+ for (stringpiece_ssize_type i = pos; i < length_; ++i) {
+ if (lookup[static_cast<unsigned char>(ptr_[i])]) {
+ return i;
+ }
+ }
+ return npos;
+}
+
+stringpiece_ssize_type StringPiece::find_first_not_of(StringPiece s,
+ size_type pos) const {
+ if (length_ <= 0) return npos;
+ if (s.length_ <= 0) return 0;
+ // Avoid the cost of BuildLookupTable() for a single-character search.
+ if (s.length_ == 1) return find_first_not_of(s.ptr_[0], pos);
+
+ bool lookup[UCHAR_MAX + 1] = { false };
+ BuildLookupTable(s, lookup);
+ for (stringpiece_ssize_type i = pos; i < length_; ++i) {
+ if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
+ return i;
+ }
+ }
+ return npos;
+}
+
+stringpiece_ssize_type StringPiece::find_first_not_of(char c,
+ size_type pos) const {
+ if (length_ <= 0) return npos;
+
+ for (; pos < static_cast<size_type>(length_); ++pos) {
+ if (ptr_[pos] != c) {
+ return pos;
+ }
+ }
+ return npos;
+}
+
+stringpiece_ssize_type StringPiece::find_last_of(StringPiece s,
+ size_type pos) const {
+ if (length_ <= 0 || s.length_ <= 0) return npos;
+ // Avoid the cost of BuildLookupTable() for a single-character search.
+ if (s.length_ == 1) return find_last_of(s.ptr_[0], pos);
+
+ bool lookup[UCHAR_MAX + 1] = { false };
+ BuildLookupTable(s, lookup);
+ for (stringpiece_ssize_type i =
+ std::min(pos, static_cast<size_type>(length_ - 1)); i >= 0; --i) {
+ if (lookup[static_cast<unsigned char>(ptr_[i])]) {
+ return i;
+ }
+ }
+ return npos;
+}
+
+stringpiece_ssize_type StringPiece::find_last_not_of(StringPiece s,
+ size_type pos) const {
+ if (length_ <= 0) return npos;
+
+ stringpiece_ssize_type i = std::min(pos, static_cast<size_type>(length_ - 1));
+ if (s.length_ <= 0) return i;
+
+ // Avoid the cost of BuildLookupTable() for a single-character search.
+ if (s.length_ == 1) return find_last_not_of(s.ptr_[0], pos);
+
+ bool lookup[UCHAR_MAX + 1] = { false };
+ BuildLookupTable(s, lookup);
+ for (; i >= 0; --i) {
+ if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
+ return i;
+ }
+ }
+ return npos;
+}
+
+stringpiece_ssize_type StringPiece::find_last_not_of(char c,
+ size_type pos) const {
+ if (length_ <= 0) return npos;
+
+ for (stringpiece_ssize_type i =
+ std::min(pos, static_cast<size_type>(length_ - 1)); i >= 0; --i) {
+ if (ptr_[i] != c) {
+ return i;
+ }
+ }
+ return npos;
+}
+
+StringPiece StringPiece::substr(size_type pos, size_type n) const {
+ if (pos > length_) pos = length_;
+ if (n > length_ - pos) n = length_ - pos;
+ return StringPiece(ptr_ + pos, n);
+}
+
+const StringPiece::size_type StringPiece::npos = size_type(-1);
+
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/stringpiece.h b/src/google/protobuf/stubs/stringpiece.h
new file mode 100644
index 00000000..353a60d3
--- /dev/null
+++ b/src/google/protobuf/stubs/stringpiece.h
@@ -0,0 +1,440 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A StringPiece points to part or all of a string, Cord, double-quoted string
+// literal, or other string-like object. A StringPiece does *not* own the
+// string to which it points. A StringPiece is not null-terminated.
+//
+// You can use StringPiece as a function or method parameter. A StringPiece
+// parameter can receive a double-quoted string literal argument, a "const
+// char*" argument, a string argument, or a StringPiece argument with no data
+// copying. Systematic use of StringPiece for arguments reduces data
+// copies and strlen() calls.
+//
+// Prefer passing StringPieces by value:
+// void MyFunction(StringPiece arg);
+// If circumstances require, you may also pass by const reference:
+// void MyFunction(const StringPiece& arg); // not preferred
+// Both of these have the same lifetime semantics. Passing by value
+// generates slightly smaller code. For more discussion, see the thread
+// go/stringpiecebyvalue on c-users.
+//
+// StringPiece is also suitable for local variables if you know that
+// the lifetime of the underlying object is longer than the lifetime
+// of your StringPiece variable.
+//
+// Beware of binding a StringPiece to a temporary:
+// StringPiece sp = obj.MethodReturningString(); // BAD: lifetime problem
+//
+// This code is okay:
+// string str = obj.MethodReturningString(); // str owns its contents
+// StringPiece sp(str); // GOOD, because str outlives sp
+//
+// StringPiece is sometimes a poor choice for a return value and usually a poor
+// choice for a data member. If you do use a StringPiece this way, it is your
+// responsibility to ensure that the object pointed to by the StringPiece
+// outlives the StringPiece.
+//
+// A StringPiece may represent just part of a string; thus the name "Piece".
+// For example, when splitting a string, vector<StringPiece> is a natural data
+// type for the output. For another example, a Cord is a non-contiguous,
+// potentially very long string-like object. The Cord class has an interface
+// that iteratively provides StringPiece objects that point to the
+// successive pieces of a Cord object.
+//
+// A StringPiece is not null-terminated. If you write code that scans a
+// StringPiece, you must check its length before reading any characters.
+// Common idioms that work on null-terminated strings do not work on
+// StringPiece objects.
+//
+// There are several ways to create a null StringPiece:
+// StringPiece()
+// StringPiece(NULL)
+// StringPiece(NULL, 0)
+// For all of the above, sp.data() == NULL, sp.length() == 0,
+// and sp.empty() == true. Also, if you create a StringPiece with
+// a non-NULL pointer then sp.data() != NULL. Once created,
+// sp.data() will stay either NULL or not-NULL, except if you call
+// sp.clear() or sp.set().
+//
+// Thus, you can use StringPiece(NULL) to signal an out-of-band value
+// that is different from other StringPiece values. This is similar
+// to the way that const char* p1 = NULL; is different from
+// const char* p2 = "";.
+//
+// There are many ways to create an empty StringPiece:
+// StringPiece()
+// StringPiece(NULL)
+// StringPiece(NULL, 0)
+// StringPiece("")
+// StringPiece("", 0)
+// StringPiece("abcdef", 0)
+// StringPiece("abcdef"+6, 0)
+// For all of the above, sp.length() will be 0 and sp.empty() will be true.
+// For some empty StringPiece values, sp.data() will be NULL.
+// For some empty StringPiece values, sp.data() will not be NULL.
+//
+// Be careful not to confuse: null StringPiece and empty StringPiece.
+// The set of empty StringPieces properly includes the set of null StringPieces.
+// That is, every null StringPiece is an empty StringPiece,
+// but some non-null StringPieces are empty Stringpieces too.
+//
+// All empty StringPiece values compare equal to each other.
+// Even a null StringPieces compares equal to a non-null empty StringPiece:
+// StringPiece() == StringPiece("", 0)
+// StringPiece(NULL) == StringPiece("abc", 0)
+// StringPiece(NULL, 0) == StringPiece("abcdef"+6, 0)
+//
+// Look carefully at this example:
+// StringPiece("") == NULL
+// True or false? TRUE, because StringPiece::operator== converts
+// the right-hand side from NULL to StringPiece(NULL),
+// and then compares two zero-length spans of characters.
+// However, we are working to make this example produce a compile error.
+//
+// Suppose you want to write:
+// bool TestWhat?(StringPiece sp) { return sp == NULL; } // BAD
+// Do not do that. Write one of these instead:
+// bool TestNull(StringPiece sp) { return sp.data() == NULL; }
+// bool TestEmpty(StringPiece sp) { return sp.empty(); }
+// The intent of TestWhat? is unclear. Did you mean TestNull or TestEmpty?
+// Right now, TestWhat? behaves likes TestEmpty.
+// We are working to make TestWhat? produce a compile error.
+// TestNull is good to test for an out-of-band signal.
+// TestEmpty is good to test for an empty StringPiece.
+//
+// Caveats (again):
+// (1) The lifetime of the pointed-to string (or piece of a string)
+// must be longer than the lifetime of the StringPiece.
+// (2) There may or may not be a '\0' character after the end of
+// StringPiece data.
+// (3) A null StringPiece is empty.
+// An empty StringPiece may or may not be a null StringPiece.
+
+#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_
+#define GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_
+
+#include <assert.h>
+#include <stddef.h>
+#include <string.h>
+#include <iosfwd>
+#include <limits>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+// StringPiece has *two* size types.
+// StringPiece::size_type
+// is unsigned
+// is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64
+// no future changes intended
+// stringpiece_ssize_type
+// is signed
+// is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64
+// future changes intended: http://go/64BitStringPiece
+//
+typedef string::difference_type stringpiece_ssize_type;
+
+// STRINGPIECE_CHECK_SIZE protects us from 32-bit overflows.
+// TODO(mec): delete this after stringpiece_ssize_type goes 64 bit.
+#if !defined(NDEBUG)
+#define STRINGPIECE_CHECK_SIZE 1
+#elif defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
+#define STRINGPIECE_CHECK_SIZE 1
+#else
+#define STRINGPIECE_CHECK_SIZE 0
+#endif
+
+class LIBPROTOBUF_EXPORT StringPiece {
+ private:
+ const char* ptr_;
+ stringpiece_ssize_type length_;
+
+ // Prevent overflow in debug mode or fortified mode.
+ // sizeof(stringpiece_ssize_type) may be smaller than sizeof(size_t).
+ static stringpiece_ssize_type CheckedSsizeTFromSizeT(size_t size) {
+#if STRINGPIECE_CHECK_SIZE > 0
+#ifdef max
+#undef max
+#endif
+ if (size > static_cast<size_t>(
+ std::numeric_limits<stringpiece_ssize_type>::max())) {
+ // Some people grep for this message in logs
+ // so take care if you ever change it.
+ LogFatalSizeTooBig(size, "size_t to int conversion");
+ }
+#endif
+ return static_cast<stringpiece_ssize_type>(size);
+ }
+
+ // Out-of-line error path.
+ static void LogFatalSizeTooBig(size_t size, const char* details);
+
+ public:
+ // We provide non-explicit singleton constructors so users can pass
+ // in a "const char*" or a "string" wherever a "StringPiece" is
+ // expected.
+ //
+ // Style guide exception granted:
+ // http://goto/style-guide-exception-20978288
+ StringPiece() : ptr_(NULL), length_(0) {}
+
+ StringPiece(const char* str) // NOLINT(runtime/explicit)
+ : ptr_(str), length_(0) {
+ if (str != NULL) {
+ length_ = CheckedSsizeTFromSizeT(strlen(str));
+ }
+ }
+
+ template <class Allocator>
+ StringPiece( // NOLINT(runtime/explicit)
+ const std::basic_string<char, std::char_traits<char>, Allocator>& str)
+ : ptr_(str.data()), length_(0) {
+ length_ = CheckedSsizeTFromSizeT(str.size());
+ }
+#if defined(HAS_GLOBAL_STRING)
+ template <class Allocator>
+ StringPiece( // NOLINT(runtime/explicit)
+ const basic_string<char, std::char_traits<char>, Allocator>& str)
+ : ptr_(str.data()), length_(0) {
+ length_ = CheckedSsizeTFromSizeT(str.size());
+ }
+#endif
+
+ StringPiece(const char* offset, stringpiece_ssize_type len)
+ : ptr_(offset), length_(len) {
+ assert(len >= 0);
+ }
+
+ // Substring of another StringPiece.
+ // pos must be non-negative and <= x.length().
+ StringPiece(StringPiece x, stringpiece_ssize_type pos);
+ // Substring of another StringPiece.
+ // pos must be non-negative and <= x.length().
+ // len must be non-negative and will be pinned to at most x.length() - pos.
+ StringPiece(StringPiece x,
+ stringpiece_ssize_type pos,
+ stringpiece_ssize_type len);
+
+ // data() may return a pointer to a buffer with embedded NULs, and the
+ // returned buffer may or may not be null terminated. Therefore it is
+ // typically a mistake to pass data() to a routine that expects a NUL
+ // terminated string.
+ const char* data() const { return ptr_; }
+ stringpiece_ssize_type size() const { return length_; }
+ stringpiece_ssize_type length() const { return length_; }
+ bool empty() const { return length_ == 0; }
+
+ void clear() {
+ ptr_ = NULL;
+ length_ = 0;
+ }
+
+ void set(const char* data, stringpiece_ssize_type len) {
+ assert(len >= 0);
+ ptr_ = data;
+ length_ = len;
+ }
+
+ void set(const char* str) {
+ ptr_ = str;
+ if (str != NULL)
+ length_ = CheckedSsizeTFromSizeT(strlen(str));
+ else
+ length_ = 0;
+ }
+
+ void set(const void* data, stringpiece_ssize_type len) {
+ ptr_ = reinterpret_cast<const char*>(data);
+ length_ = len;
+ }
+
+ char operator[](stringpiece_ssize_type i) const {
+ assert(0 <= i);
+ assert(i < length_);
+ return ptr_[i];
+ }
+
+ void remove_prefix(stringpiece_ssize_type n) {
+ assert(length_ >= n);
+ ptr_ += n;
+ length_ -= n;
+ }
+
+ void remove_suffix(stringpiece_ssize_type n) {
+ assert(length_ >= n);
+ length_ -= n;
+ }
+
+ // returns {-1, 0, 1}
+ int compare(StringPiece x) const {
+ const stringpiece_ssize_type min_size =
+ length_ < x.length_ ? length_ : x.length_;
+ int r = memcmp(ptr_, x.ptr_, min_size);
+ if (r < 0) return -1;
+ if (r > 0) return 1;
+ if (length_ < x.length_) return -1;
+ if (length_ > x.length_) return 1;
+ return 0;
+ }
+
+ string as_string() const {
+ return ToString();
+ }
+ // We also define ToString() here, since many other string-like
+ // interfaces name the routine that converts to a C++ string
+ // "ToString", and it's confusing to have the method that does that
+ // for a StringPiece be called "as_string()". We also leave the
+ // "as_string()" method defined here for existing code.
+ string ToString() const {
+ if (ptr_ == NULL) return string();
+ return string(data(), size());
+ }
+
+ operator string() const {
+ return ToString();
+ }
+
+ void CopyToString(string* target) const;
+ void AppendToString(string* target) const;
+
+ bool starts_with(StringPiece x) const {
+ return (length_ >= x.length_) && (memcmp(ptr_, x.ptr_, x.length_) == 0);
+ }
+
+ bool ends_with(StringPiece x) const {
+ return ((length_ >= x.length_) &&
+ (memcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0));
+ }
+
+ // Checks whether StringPiece starts with x and if so advances the beginning
+ // of it to past the match. It's basically a shortcut for starts_with
+ // followed by remove_prefix.
+ bool Consume(StringPiece x);
+ // Like above but for the end of the string.
+ bool ConsumeFromEnd(StringPiece x);
+
+ // standard STL container boilerplate
+ typedef char value_type;
+ typedef const char* pointer;
+ typedef const char& reference;
+ typedef const char& const_reference;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ static const size_type npos;
+ typedef const char* const_iterator;
+ typedef const char* iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ iterator begin() const { return ptr_; }
+ iterator end() const { return ptr_ + length_; }
+ const_reverse_iterator rbegin() const {
+ return const_reverse_iterator(ptr_ + length_);
+ }
+ const_reverse_iterator rend() const {
+ return const_reverse_iterator(ptr_);
+ }
+ stringpiece_ssize_type max_size() const { return length_; }
+ stringpiece_ssize_type capacity() const { return length_; }
+
+ // cpplint.py emits a false positive [build/include_what_you_use]
+ stringpiece_ssize_type copy(char* buf, size_type n, size_type pos = 0) const; // NOLINT
+
+ bool contains(StringPiece s) const;
+
+ stringpiece_ssize_type find(StringPiece s, size_type pos = 0) const;
+ stringpiece_ssize_type find(char c, size_type pos = 0) const;
+ stringpiece_ssize_type rfind(StringPiece s, size_type pos = npos) const;
+ stringpiece_ssize_type rfind(char c, size_type pos = npos) const;
+
+ stringpiece_ssize_type find_first_of(StringPiece s, size_type pos = 0) const;
+ stringpiece_ssize_type find_first_of(char c, size_type pos = 0) const {
+ return find(c, pos);
+ }
+ stringpiece_ssize_type find_first_not_of(StringPiece s,
+ size_type pos = 0) const;
+ stringpiece_ssize_type find_first_not_of(char c, size_type pos = 0) const;
+ stringpiece_ssize_type find_last_of(StringPiece s,
+ size_type pos = npos) const;
+ stringpiece_ssize_type find_last_of(char c, size_type pos = npos) const {
+ return rfind(c, pos);
+ }
+ stringpiece_ssize_type find_last_not_of(StringPiece s,
+ size_type pos = npos) const;
+ stringpiece_ssize_type find_last_not_of(char c, size_type pos = npos) const;
+
+ StringPiece substr(size_type pos, size_type n = npos) const;
+};
+
+// This large function is defined inline so that in a fairly common case where
+// one of the arguments is a literal, the compiler can elide a lot of the
+// following comparisons.
+inline bool operator==(StringPiece x, StringPiece y) {
+ stringpiece_ssize_type len = x.size();
+ if (len != y.size()) {
+ return false;
+ }
+
+ return x.data() == y.data() || len <= 0 ||
+ memcmp(x.data(), y.data(), len) == 0;
+}
+
+inline bool operator!=(StringPiece x, StringPiece y) {
+ return !(x == y);
+}
+
+inline bool operator<(StringPiece x, StringPiece y) {
+ const stringpiece_ssize_type min_size =
+ x.size() < y.size() ? x.size() : y.size();
+ const int r = memcmp(x.data(), y.data(), min_size);
+ return (r < 0) || (r == 0 && x.size() < y.size());
+}
+
+inline bool operator>(StringPiece x, StringPiece y) {
+ return y < x;
+}
+
+inline bool operator<=(StringPiece x, StringPiece y) {
+ return !(x > y);
+}
+
+inline bool operator>=(StringPiece x, StringPiece y) {
+ return !(x < y);
+}
+
+// allow StringPiece to be logged
+extern std::ostream& operator<<(std::ostream& o, StringPiece piece);
+
+} // namespace protobuf
+} // namespace google
+
+#endif // STRINGS_STRINGPIECE_H_
diff --git a/src/google/protobuf/stubs/stringpiece_unittest.cc b/src/google/protobuf/stubs/stringpiece_unittest.cc
new file mode 100644
index 00000000..9b5dae13
--- /dev/null
+++ b/src/google/protobuf/stubs/stringpiece_unittest.cc
@@ -0,0 +1,793 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include <google/protobuf/stubs/stringpiece.h>
+
+#include <iterator>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+TEST(StringPiece, Ctor) {
+ {
+ // Null.
+ StringPiece s10;
+ EXPECT_TRUE(s10.data() == NULL);
+ EXPECT_EQ(0, s10.length());
+ }
+
+ {
+ // const char* without length.
+ const char* hello = "hello";
+ StringPiece s20(hello);
+ EXPECT_TRUE(s20.data() == hello);
+ EXPECT_EQ(5, s20.length());
+
+ // const char* with length.
+ StringPiece s21(hello, 4);
+ EXPECT_TRUE(s21.data() == hello);
+ EXPECT_EQ(4, s21.length());
+
+ // Not recommended, but valid C++
+ StringPiece s22(hello, 6);
+ EXPECT_TRUE(s22.data() == hello);
+ EXPECT_EQ(6, s22.length());
+ }
+
+ {
+ // std::string.
+ std::string hola = "hola";
+ StringPiece s30(hola);
+ EXPECT_TRUE(s30.data() == hola.data());
+ EXPECT_EQ(4, s30.length());
+
+ // std::string with embedded '\0'.
+ hola.push_back('\0');
+ hola.append("h2");
+ hola.push_back('\0');
+ StringPiece s31(hola);
+ EXPECT_TRUE(s31.data() == hola.data());
+ EXPECT_EQ(8, s31.length());
+ }
+
+#if defined(HAS_GLOBAL_STRING)
+ {
+ // ::string
+ string bonjour = "bonjour";
+ StringPiece s40(bonjour);
+ EXPECT_TRUE(s40.data() == bonjour.data());
+ EXPECT_EQ(7, s40.length());
+ }
+#endif
+
+ // TODO(mec): StringPiece(StringPiece x, int pos);
+ // TODO(mec): StringPiece(StringPiece x, int pos, int len);
+ // TODO(mec): StringPiece(const StringPiece&);
+}
+
+TEST(StringPiece, STLComparator) {
+ string s1("foo");
+ string s2("bar");
+ string s3("baz");
+
+ StringPiece p1(s1);
+ StringPiece p2(s2);
+ StringPiece p3(s3);
+
+ typedef std::map<StringPiece, int> TestMap;
+ TestMap map;
+
+ map.insert(std::make_pair(p1, 0));
+ map.insert(std::make_pair(p2, 1));
+ map.insert(std::make_pair(p3, 2));
+ EXPECT_EQ(map.size(), 3);
+
+ TestMap::const_iterator iter = map.begin();
+ EXPECT_EQ(iter->second, 1);
+ ++iter;
+ EXPECT_EQ(iter->second, 2);
+ ++iter;
+ EXPECT_EQ(iter->second, 0);
+ ++iter;
+ EXPECT_TRUE(iter == map.end());
+
+ TestMap::iterator new_iter = map.find("zot");
+ EXPECT_TRUE(new_iter == map.end());
+
+ new_iter = map.find("bar");
+ EXPECT_TRUE(new_iter != map.end());
+
+ map.erase(new_iter);
+ EXPECT_EQ(map.size(), 2);
+
+ iter = map.begin();
+ EXPECT_EQ(iter->second, 2);
+ ++iter;
+ EXPECT_EQ(iter->second, 0);
+ ++iter;
+ EXPECT_TRUE(iter == map.end());
+}
+
+TEST(StringPiece, ComparisonOperators) {
+#define COMPARE(result, op, x, y) \
+ EXPECT_EQ(result, StringPiece((x)) op StringPiece((y))); \
+ EXPECT_EQ(result, StringPiece((x)).compare(StringPiece((y))) op 0)
+
+ COMPARE(true, ==, "", "");
+ COMPARE(true, ==, "", NULL);
+ COMPARE(true, ==, NULL, "");
+ COMPARE(true, ==, "a", "a");
+ COMPARE(true, ==, "aa", "aa");
+ COMPARE(false, ==, "a", "");
+ COMPARE(false, ==, "", "a");
+ COMPARE(false, ==, "a", "b");
+ COMPARE(false, ==, "a", "aa");
+ COMPARE(false, ==, "aa", "a");
+
+ COMPARE(false, !=, "", "");
+ COMPARE(false, !=, "a", "a");
+ COMPARE(false, !=, "aa", "aa");
+ COMPARE(true, !=, "a", "");
+ COMPARE(true, !=, "", "a");
+ COMPARE(true, !=, "a", "b");
+ COMPARE(true, !=, "a", "aa");
+ COMPARE(true, !=, "aa", "a");
+
+ COMPARE(true, <, "a", "b");
+ COMPARE(true, <, "a", "aa");
+ COMPARE(true, <, "aa", "b");
+ COMPARE(true, <, "aa", "bb");
+ COMPARE(false, <, "a", "a");
+ COMPARE(false, <, "b", "a");
+ COMPARE(false, <, "aa", "a");
+ COMPARE(false, <, "b", "aa");
+ COMPARE(false, <, "bb", "aa");
+
+ COMPARE(true, <=, "a", "a");
+ COMPARE(true, <=, "a", "b");
+ COMPARE(true, <=, "a", "aa");
+ COMPARE(true, <=, "aa", "b");
+ COMPARE(true, <=, "aa", "bb");
+ COMPARE(false, <=, "b", "a");
+ COMPARE(false, <=, "aa", "a");
+ COMPARE(false, <=, "b", "aa");
+ COMPARE(false, <=, "bb", "aa");
+
+ COMPARE(false, >=, "a", "b");
+ COMPARE(false, >=, "a", "aa");
+ COMPARE(false, >=, "aa", "b");
+ COMPARE(false, >=, "aa", "bb");
+ COMPARE(true, >=, "a", "a");
+ COMPARE(true, >=, "b", "a");
+ COMPARE(true, >=, "aa", "a");
+ COMPARE(true, >=, "b", "aa");
+ COMPARE(true, >=, "bb", "aa");
+
+ COMPARE(false, >, "a", "a");
+ COMPARE(false, >, "a", "b");
+ COMPARE(false, >, "a", "aa");
+ COMPARE(false, >, "aa", "b");
+ COMPARE(false, >, "aa", "bb");
+ COMPARE(true, >, "b", "a");
+ COMPARE(true, >, "aa", "a");
+ COMPARE(true, >, "b", "aa");
+ COMPARE(true, >, "bb", "aa");
+
+ string x;
+ for (int i = 0; i < 256; i++) {
+ x += 'a';
+ string y = x;
+ COMPARE(true, ==, x, y);
+ for (int j = 0; j < i; j++) {
+ string z = x;
+ z[j] = 'b'; // Differs in position 'j'
+ COMPARE(false, ==, x, z);
+ COMPARE(true, <, x, z);
+ COMPARE(true, >, z, x);
+ if (j + 1 < i) {
+ z[j + 1] = 'A'; // Differs in position 'j+1' as well
+ COMPARE(false, ==, x, z);
+ COMPARE(true, <, x, z);
+ COMPARE(true, >, z, x);
+ z[j + 1] = 'z'; // Differs in position 'j+1' as well
+ COMPARE(false, ==, x, z);
+ COMPARE(true, <, x, z);
+ COMPARE(true, >, z, x);
+ }
+ }
+ }
+
+#undef COMPARE
+}
+
+TEST(StringPiece, STL1) {
+ const StringPiece a("abcdefghijklmnopqrstuvwxyz");
+ const StringPiece b("abc");
+ const StringPiece c("xyz");
+ const StringPiece d("foobar");
+ const StringPiece e;
+ string temp("123");
+ temp += '\0';
+ temp += "456";
+ const StringPiece f(temp);
+
+ EXPECT_EQ(a[6], 'g');
+ EXPECT_EQ(b[0], 'a');
+ EXPECT_EQ(c[2], 'z');
+ EXPECT_EQ(f[3], '\0');
+ EXPECT_EQ(f[5], '5');
+
+ EXPECT_EQ(*d.data(), 'f');
+ EXPECT_EQ(d.data()[5], 'r');
+ EXPECT_TRUE(e.data() == NULL);
+
+ EXPECT_EQ(*a.begin(), 'a');
+ EXPECT_EQ(*(b.begin() + 2), 'c');
+ EXPECT_EQ(*(c.end() - 1), 'z');
+
+ EXPECT_EQ(*a.rbegin(), 'z');
+ EXPECT_EQ(*(b.rbegin() + 2), 'a');
+ EXPECT_EQ(*(c.rend() - 1), 'x');
+ EXPECT_TRUE(a.rbegin() + 26 == a.rend());
+
+ EXPECT_EQ(a.size(), 26);
+ EXPECT_EQ(b.size(), 3);
+ EXPECT_EQ(c.size(), 3);
+ EXPECT_EQ(d.size(), 6);
+ EXPECT_EQ(e.size(), 0);
+ EXPECT_EQ(f.size(), 7);
+
+ EXPECT_TRUE(!d.empty());
+ EXPECT_TRUE(d.begin() != d.end());
+ EXPECT_TRUE(d.begin() + 6 == d.end());
+
+ EXPECT_TRUE(e.empty());
+ EXPECT_TRUE(e.begin() == e.end());
+
+ EXPECT_GE(a.max_size(), a.capacity());
+ EXPECT_GE(a.capacity(), a.size());
+
+ char buf[4] = { '%', '%', '%', '%' };
+ EXPECT_EQ(a.copy(buf, 4), 4);
+ EXPECT_EQ(buf[0], a[0]);
+ EXPECT_EQ(buf[1], a[1]);
+ EXPECT_EQ(buf[2], a[2]);
+ EXPECT_EQ(buf[3], a[3]);
+ EXPECT_EQ(a.copy(buf, 3, 7), 3);
+ EXPECT_EQ(buf[0], a[7]);
+ EXPECT_EQ(buf[1], a[8]);
+ EXPECT_EQ(buf[2], a[9]);
+ EXPECT_EQ(buf[3], a[3]);
+ EXPECT_EQ(c.copy(buf, 99), 3);
+ EXPECT_EQ(buf[0], c[0]);
+ EXPECT_EQ(buf[1], c[1]);
+ EXPECT_EQ(buf[2], c[2]);
+ EXPECT_EQ(buf[3], a[3]);
+}
+
+// Separated from STL1() because some compilers produce an overly
+// large stack frame for the combined function.
+TEST(StringPiece, STL2) {
+ const StringPiece a("abcdefghijklmnopqrstuvwxyz");
+ const StringPiece b("abc");
+ const StringPiece c("xyz");
+ StringPiece d("foobar");
+ const StringPiece e;
+ const StringPiece f("123" "\0" "456", 7);
+
+ d.clear();
+ EXPECT_EQ(d.size(), 0);
+ EXPECT_TRUE(d.empty());
+ EXPECT_TRUE(d.data() == NULL);
+ EXPECT_TRUE(d.begin() == d.end());
+
+ EXPECT_EQ(StringPiece::npos, string::npos);
+
+ EXPECT_EQ(a.find(b), 0);
+ EXPECT_EQ(a.find(b, 1), StringPiece::npos);
+ EXPECT_EQ(a.find(c), 23);
+ EXPECT_EQ(a.find(c, 9), 23);
+ EXPECT_EQ(a.find(c, StringPiece::npos), StringPiece::npos);
+ EXPECT_EQ(b.find(c), StringPiece::npos);
+ EXPECT_EQ(b.find(c, StringPiece::npos), StringPiece::npos);
+ EXPECT_EQ(a.find(d), 0);
+ EXPECT_EQ(a.find(e), 0);
+ EXPECT_EQ(a.find(d, 12), 12);
+ EXPECT_EQ(a.find(e, 17), 17);
+ StringPiece g("xx not found bb");
+ EXPECT_EQ(a.find(g), StringPiece::npos);
+ // empty string nonsense
+ EXPECT_EQ(d.find(b), StringPiece::npos);
+ EXPECT_EQ(e.find(b), StringPiece::npos);
+ EXPECT_EQ(d.find(b, 4), StringPiece::npos);
+ EXPECT_EQ(e.find(b, 7), StringPiece::npos);
+
+ size_t empty_search_pos = string().find(string());
+ EXPECT_EQ(d.find(d), empty_search_pos);
+ EXPECT_EQ(d.find(e), empty_search_pos);
+ EXPECT_EQ(e.find(d), empty_search_pos);
+ EXPECT_EQ(e.find(e), empty_search_pos);
+ EXPECT_EQ(d.find(d, 4), string().find(string(), 4));
+ EXPECT_EQ(d.find(e, 4), string().find(string(), 4));
+ EXPECT_EQ(e.find(d, 4), string().find(string(), 4));
+ EXPECT_EQ(e.find(e, 4), string().find(string(), 4));
+
+ EXPECT_EQ(a.find('a'), 0);
+ EXPECT_EQ(a.find('c'), 2);
+ EXPECT_EQ(a.find('z'), 25);
+ EXPECT_EQ(a.find('$'), StringPiece::npos);
+ EXPECT_EQ(a.find('\0'), StringPiece::npos);
+ EXPECT_EQ(f.find('\0'), 3);
+ EXPECT_EQ(f.find('3'), 2);
+ EXPECT_EQ(f.find('5'), 5);
+ EXPECT_EQ(g.find('o'), 4);
+ EXPECT_EQ(g.find('o', 4), 4);
+ EXPECT_EQ(g.find('o', 5), 8);
+ EXPECT_EQ(a.find('b', 5), StringPiece::npos);
+ // empty string nonsense
+ EXPECT_EQ(d.find('\0'), StringPiece::npos);
+ EXPECT_EQ(e.find('\0'), StringPiece::npos);
+ EXPECT_EQ(d.find('\0', 4), StringPiece::npos);
+ EXPECT_EQ(e.find('\0', 7), StringPiece::npos);
+ EXPECT_EQ(d.find('x'), StringPiece::npos);
+ EXPECT_EQ(e.find('x'), StringPiece::npos);
+ EXPECT_EQ(d.find('x', 4), StringPiece::npos);
+ EXPECT_EQ(e.find('x', 7), StringPiece::npos);
+
+ EXPECT_EQ(a.rfind(b), 0);
+ EXPECT_EQ(a.rfind(b, 1), 0);
+ EXPECT_EQ(a.rfind(c), 23);
+ EXPECT_EQ(a.rfind(c, 22), StringPiece::npos);
+ EXPECT_EQ(a.rfind(c, 1), StringPiece::npos);
+ EXPECT_EQ(a.rfind(c, 0), StringPiece::npos);
+ EXPECT_EQ(b.rfind(c), StringPiece::npos);
+ EXPECT_EQ(b.rfind(c, 0), StringPiece::npos);
+ EXPECT_EQ(a.rfind(d), a.as_string().rfind(string()));
+ EXPECT_EQ(a.rfind(e), a.as_string().rfind(string()));
+ EXPECT_EQ(a.rfind(d, 12), 12);
+ EXPECT_EQ(a.rfind(e, 17), 17);
+ EXPECT_EQ(a.rfind(g), StringPiece::npos);
+ EXPECT_EQ(d.rfind(b), StringPiece::npos);
+ EXPECT_EQ(e.rfind(b), StringPiece::npos);
+ EXPECT_EQ(d.rfind(b, 4), StringPiece::npos);
+ EXPECT_EQ(e.rfind(b, 7), StringPiece::npos);
+ // empty string nonsense
+ EXPECT_EQ(d.rfind(d, 4), string().rfind(string()));
+ EXPECT_EQ(e.rfind(d, 7), string().rfind(string()));
+ EXPECT_EQ(d.rfind(e, 4), string().rfind(string()));
+ EXPECT_EQ(e.rfind(e, 7), string().rfind(string()));
+ EXPECT_EQ(d.rfind(d), string().rfind(string()));
+ EXPECT_EQ(e.rfind(d), string().rfind(string()));
+ EXPECT_EQ(d.rfind(e), string().rfind(string()));
+ EXPECT_EQ(e.rfind(e), string().rfind(string()));
+
+ EXPECT_EQ(g.rfind('o'), 8);
+ EXPECT_EQ(g.rfind('q'), StringPiece::npos);
+ EXPECT_EQ(g.rfind('o', 8), 8);
+ EXPECT_EQ(g.rfind('o', 7), 4);
+ EXPECT_EQ(g.rfind('o', 3), StringPiece::npos);
+ EXPECT_EQ(f.rfind('\0'), 3);
+ EXPECT_EQ(f.rfind('\0', 12), 3);
+ EXPECT_EQ(f.rfind('3'), 2);
+ EXPECT_EQ(f.rfind('5'), 5);
+ // empty string nonsense
+ EXPECT_EQ(d.rfind('o'), StringPiece::npos);
+ EXPECT_EQ(e.rfind('o'), StringPiece::npos);
+ EXPECT_EQ(d.rfind('o', 4), StringPiece::npos);
+ EXPECT_EQ(e.rfind('o', 7), StringPiece::npos);
+
+ EXPECT_EQ(a.find_first_of(b), 0);
+ EXPECT_EQ(a.find_first_of(b, 0), 0);
+ EXPECT_EQ(a.find_first_of(b, 1), 1);
+ EXPECT_EQ(a.find_first_of(b, 2), 2);
+ EXPECT_EQ(a.find_first_of(b, 3), StringPiece::npos);
+ EXPECT_EQ(a.find_first_of(c), 23);
+ EXPECT_EQ(a.find_first_of(c, 23), 23);
+ EXPECT_EQ(a.find_first_of(c, 24), 24);
+ EXPECT_EQ(a.find_first_of(c, 25), 25);
+ EXPECT_EQ(a.find_first_of(c, 26), StringPiece::npos);
+ EXPECT_EQ(g.find_first_of(b), 13);
+ EXPECT_EQ(g.find_first_of(c), 0);
+ EXPECT_EQ(a.find_first_of(f), StringPiece::npos);
+ EXPECT_EQ(f.find_first_of(a), StringPiece::npos);
+ // empty string nonsense
+ EXPECT_EQ(a.find_first_of(d), StringPiece::npos);
+ EXPECT_EQ(a.find_first_of(e), StringPiece::npos);
+ EXPECT_EQ(d.find_first_of(b), StringPiece::npos);
+ EXPECT_EQ(e.find_first_of(b), StringPiece::npos);
+ EXPECT_EQ(d.find_first_of(d), StringPiece::npos);
+ EXPECT_EQ(e.find_first_of(d), StringPiece::npos);
+ EXPECT_EQ(d.find_first_of(e), StringPiece::npos);
+ EXPECT_EQ(e.find_first_of(e), StringPiece::npos);
+
+ EXPECT_EQ(a.find_first_not_of(b), 3);
+ EXPECT_EQ(a.find_first_not_of(c), 0);
+ EXPECT_EQ(b.find_first_not_of(a), StringPiece::npos);
+ EXPECT_EQ(c.find_first_not_of(a), StringPiece::npos);
+ EXPECT_EQ(f.find_first_not_of(a), 0);
+ EXPECT_EQ(a.find_first_not_of(f), 0);
+ EXPECT_EQ(a.find_first_not_of(d), 0);
+ EXPECT_EQ(a.find_first_not_of(e), 0);
+ // empty string nonsense
+ EXPECT_EQ(d.find_first_not_of(a), StringPiece::npos);
+ EXPECT_EQ(e.find_first_not_of(a), StringPiece::npos);
+ EXPECT_EQ(d.find_first_not_of(d), StringPiece::npos);
+ EXPECT_EQ(e.find_first_not_of(d), StringPiece::npos);
+ EXPECT_EQ(d.find_first_not_of(e), StringPiece::npos);
+ EXPECT_EQ(e.find_first_not_of(e), StringPiece::npos);
+
+ StringPiece h("====");
+ EXPECT_EQ(h.find_first_not_of('='), StringPiece::npos);
+ EXPECT_EQ(h.find_first_not_of('=', 3), StringPiece::npos);
+ EXPECT_EQ(h.find_first_not_of('\0'), 0);
+ EXPECT_EQ(g.find_first_not_of('x'), 2);
+ EXPECT_EQ(f.find_first_not_of('\0'), 0);
+ EXPECT_EQ(f.find_first_not_of('\0', 3), 4);
+ EXPECT_EQ(f.find_first_not_of('\0', 2), 2);
+ // empty string nonsense
+ EXPECT_EQ(d.find_first_not_of('x'), StringPiece::npos);
+ EXPECT_EQ(e.find_first_not_of('x'), StringPiece::npos);
+ EXPECT_EQ(d.find_first_not_of('\0'), StringPiece::npos);
+ EXPECT_EQ(e.find_first_not_of('\0'), StringPiece::npos);
+
+ // StringPiece g("xx not found bb");
+ StringPiece i("56");
+ EXPECT_EQ(h.find_last_of(a), StringPiece::npos);
+ EXPECT_EQ(g.find_last_of(a), g.size()-1);
+ EXPECT_EQ(a.find_last_of(b), 2);
+ EXPECT_EQ(a.find_last_of(c), a.size()-1);
+ EXPECT_EQ(f.find_last_of(i), 6);
+ EXPECT_EQ(a.find_last_of('a'), 0);
+ EXPECT_EQ(a.find_last_of('b'), 1);
+ EXPECT_EQ(a.find_last_of('z'), 25);
+ EXPECT_EQ(a.find_last_of('a', 5), 0);
+ EXPECT_EQ(a.find_last_of('b', 5), 1);
+ EXPECT_EQ(a.find_last_of('b', 0), StringPiece::npos);
+ EXPECT_EQ(a.find_last_of('z', 25), 25);
+ EXPECT_EQ(a.find_last_of('z', 24), StringPiece::npos);
+ EXPECT_EQ(f.find_last_of(i, 5), 5);
+ EXPECT_EQ(f.find_last_of(i, 6), 6);
+ EXPECT_EQ(f.find_last_of(a, 4), StringPiece::npos);
+ // empty string nonsense
+ EXPECT_EQ(f.find_last_of(d), StringPiece::npos);
+ EXPECT_EQ(f.find_last_of(e), StringPiece::npos);
+ EXPECT_EQ(f.find_last_of(d, 4), StringPiece::npos);
+ EXPECT_EQ(f.find_last_of(e, 4), StringPiece::npos);
+ EXPECT_EQ(d.find_last_of(d), StringPiece::npos);
+ EXPECT_EQ(d.find_last_of(e), StringPiece::npos);
+ EXPECT_EQ(e.find_last_of(d), StringPiece::npos);
+ EXPECT_EQ(e.find_last_of(e), StringPiece::npos);
+ EXPECT_EQ(d.find_last_of(f), StringPiece::npos);
+ EXPECT_EQ(e.find_last_of(f), StringPiece::npos);
+ EXPECT_EQ(d.find_last_of(d, 4), StringPiece::npos);
+ EXPECT_EQ(d.find_last_of(e, 4), StringPiece::npos);
+ EXPECT_EQ(e.find_last_of(d, 4), StringPiece::npos);
+ EXPECT_EQ(e.find_last_of(e, 4), StringPiece::npos);
+ EXPECT_EQ(d.find_last_of(f, 4), StringPiece::npos);
+ EXPECT_EQ(e.find_last_of(f, 4), StringPiece::npos);
+
+ EXPECT_EQ(a.find_last_not_of(b), a.size()-1);
+ EXPECT_EQ(a.find_last_not_of(c), 22);
+ EXPECT_EQ(b.find_last_not_of(a), StringPiece::npos);
+ EXPECT_EQ(b.find_last_not_of(b), StringPiece::npos);
+ EXPECT_EQ(f.find_last_not_of(i), 4);
+ EXPECT_EQ(a.find_last_not_of(c, 24), 22);
+ EXPECT_EQ(a.find_last_not_of(b, 3), 3);
+ EXPECT_EQ(a.find_last_not_of(b, 2), StringPiece::npos);
+ // empty string nonsense
+ EXPECT_EQ(f.find_last_not_of(d), f.size()-1);
+ EXPECT_EQ(f.find_last_not_of(e), f.size()-1);
+ EXPECT_EQ(f.find_last_not_of(d, 4), 4);
+ EXPECT_EQ(f.find_last_not_of(e, 4), 4);
+ EXPECT_EQ(d.find_last_not_of(d), StringPiece::npos);
+ EXPECT_EQ(d.find_last_not_of(e), StringPiece::npos);
+ EXPECT_EQ(e.find_last_not_of(d), StringPiece::npos);
+ EXPECT_EQ(e.find_last_not_of(e), StringPiece::npos);
+ EXPECT_EQ(d.find_last_not_of(f), StringPiece::npos);
+ EXPECT_EQ(e.find_last_not_of(f), StringPiece::npos);
+ EXPECT_EQ(d.find_last_not_of(d, 4), StringPiece::npos);
+ EXPECT_EQ(d.find_last_not_of(e, 4), StringPiece::npos);
+ EXPECT_EQ(e.find_last_not_of(d, 4), StringPiece::npos);
+ EXPECT_EQ(e.find_last_not_of(e, 4), StringPiece::npos);
+ EXPECT_EQ(d.find_last_not_of(f, 4), StringPiece::npos);
+ EXPECT_EQ(e.find_last_not_of(f, 4), StringPiece::npos);
+
+ EXPECT_EQ(h.find_last_not_of('x'), h.size() - 1);
+ EXPECT_EQ(h.find_last_not_of('='), StringPiece::npos);
+ EXPECT_EQ(b.find_last_not_of('c'), 1);
+ EXPECT_EQ(h.find_last_not_of('x', 2), 2);
+ EXPECT_EQ(h.find_last_not_of('=', 2), StringPiece::npos);
+ EXPECT_EQ(b.find_last_not_of('b', 1), 0);
+ // empty string nonsense
+ EXPECT_EQ(d.find_last_not_of('x'), StringPiece::npos);
+ EXPECT_EQ(e.find_last_not_of('x'), StringPiece::npos);
+ EXPECT_EQ(d.find_last_not_of('\0'), StringPiece::npos);
+ EXPECT_EQ(e.find_last_not_of('\0'), StringPiece::npos);
+
+ EXPECT_EQ(a.substr(0, 3), b);
+ EXPECT_EQ(a.substr(23), c);
+ EXPECT_EQ(a.substr(23, 3), c);
+ EXPECT_EQ(a.substr(23, 99), c);
+ EXPECT_EQ(a.substr(0), a);
+ EXPECT_EQ(a.substr(3, 2), "de");
+ // empty string nonsense
+ EXPECT_EQ(a.substr(99, 2), e);
+ EXPECT_EQ(d.substr(99), e);
+ EXPECT_EQ(d.substr(0, 99), e);
+ EXPECT_EQ(d.substr(99, 99), e);
+ // use of npos
+ EXPECT_EQ(a.substr(0, StringPiece::npos), a);
+ EXPECT_EQ(a.substr(23, StringPiece::npos), c);
+ EXPECT_EQ(a.substr(StringPiece::npos, 0), e);
+ EXPECT_EQ(a.substr(StringPiece::npos, 1), e);
+ EXPECT_EQ(a.substr(StringPiece::npos, StringPiece::npos), e);
+
+ // Substring constructors.
+ EXPECT_EQ(StringPiece(a, 0, 3), b);
+ EXPECT_EQ(StringPiece(a, 23), c);
+ EXPECT_EQ(StringPiece(a, 23, 3), c);
+ EXPECT_EQ(StringPiece(a, 23, 99), c);
+ EXPECT_EQ(StringPiece(a, 0), a);
+ EXPECT_EQ(StringPiece(a, 3, 2), "de");
+ // empty string nonsense
+ EXPECT_EQ(StringPiece(d, 0, 99), e);
+ // Verify that they work taking an actual string, not just a StringPiece.
+ string a2 = a.as_string();
+ EXPECT_EQ(StringPiece(a2, 0, 3), b);
+ EXPECT_EQ(StringPiece(a2, 23), c);
+ EXPECT_EQ(StringPiece(a2, 23, 3), c);
+ EXPECT_EQ(StringPiece(a2, 23, 99), c);
+ EXPECT_EQ(StringPiece(a2, 0), a);
+ EXPECT_EQ(StringPiece(a2, 3, 2), "de");
+}
+
+TEST(StringPiece, Custom) {
+ StringPiece a("foobar");
+ string s1("123");
+ s1 += '\0';
+ s1 += "456";
+ StringPiece b(s1);
+ StringPiece e;
+ string s2;
+
+ // CopyToString
+ a.CopyToString(&s2);
+ EXPECT_EQ(s2.size(), 6);
+ EXPECT_EQ(s2, "foobar");
+ b.CopyToString(&s2);
+ EXPECT_EQ(s2.size(), 7);
+ EXPECT_EQ(s1, s2);
+ e.CopyToString(&s2);
+ EXPECT_TRUE(s2.empty());
+
+ // AppendToString
+ s2.erase();
+ a.AppendToString(&s2);
+ EXPECT_EQ(s2.size(), 6);
+ EXPECT_EQ(s2, "foobar");
+ a.AppendToString(&s2);
+ EXPECT_EQ(s2.size(), 12);
+ EXPECT_EQ(s2, "foobarfoobar");
+
+ // starts_with
+ EXPECT_TRUE(a.starts_with(a));
+ EXPECT_TRUE(a.starts_with("foo"));
+ EXPECT_TRUE(a.starts_with(e));
+ EXPECT_TRUE(b.starts_with(s1));
+ EXPECT_TRUE(b.starts_with(b));
+ EXPECT_TRUE(b.starts_with(e));
+ EXPECT_TRUE(e.starts_with(""));
+ EXPECT_TRUE(!a.starts_with(b));
+ EXPECT_TRUE(!b.starts_with(a));
+ EXPECT_TRUE(!e.starts_with(a));
+
+ // ends with
+ EXPECT_TRUE(a.ends_with(a));
+ EXPECT_TRUE(a.ends_with("bar"));
+ EXPECT_TRUE(a.ends_with(e));
+ EXPECT_TRUE(b.ends_with(s1));
+ EXPECT_TRUE(b.ends_with(b));
+ EXPECT_TRUE(b.ends_with(e));
+ EXPECT_TRUE(e.ends_with(""));
+ EXPECT_TRUE(!a.ends_with(b));
+ EXPECT_TRUE(!b.ends_with(a));
+ EXPECT_TRUE(!e.ends_with(a));
+
+ // remove_prefix
+ StringPiece c(a);
+ c.remove_prefix(3);
+ EXPECT_EQ(c, "bar");
+ c = a;
+ c.remove_prefix(0);
+ EXPECT_EQ(c, a);
+ c.remove_prefix(c.size());
+ EXPECT_EQ(c, e);
+
+ // remove_suffix
+ c = a;
+ c.remove_suffix(3);
+ EXPECT_EQ(c, "foo");
+ c = a;
+ c.remove_suffix(0);
+ EXPECT_EQ(c, a);
+ c.remove_suffix(c.size());
+ EXPECT_EQ(c, e);
+
+ // set
+ c.set("foobar", 6);
+ EXPECT_EQ(c, a);
+ c.set("foobar", 0);
+ EXPECT_EQ(c, e);
+ c.set("foobar", 7);
+ EXPECT_NE(c, a);
+
+ c.set("foobar");
+ EXPECT_EQ(c, a);
+
+ c.set(static_cast<const void*>("foobar"), 6);
+ EXPECT_EQ(c, a);
+ c.set(static_cast<const void*>("foobar"), 0);
+ EXPECT_EQ(c, e);
+ c.set(static_cast<const void*>("foobar"), 7);
+ EXPECT_NE(c, a);
+
+ // as_string
+ string s3(a.as_string().c_str(), 7);
+ EXPECT_EQ(c, s3);
+ string s4(e.as_string());
+ EXPECT_TRUE(s4.empty());
+
+ // ToString
+ {
+ string s5(a.ToString().c_str(), 7);
+ EXPECT_EQ(c, s5);
+ string s6(e.ToString());
+ EXPECT_TRUE(s6.empty());
+ }
+
+ // Consume
+ a.set("foobar");
+ EXPECT_TRUE(a.Consume("foo"));
+ EXPECT_EQ(a, "bar");
+ EXPECT_FALSE(a.Consume("foo"));
+ EXPECT_FALSE(a.Consume("barbar"));
+ EXPECT_FALSE(a.Consume("ar"));
+ EXPECT_EQ(a, "bar");
+
+ a.set("foobar");
+ EXPECT_TRUE(a.ConsumeFromEnd("bar"));
+ EXPECT_EQ(a, "foo");
+ EXPECT_FALSE(a.ConsumeFromEnd("bar"));
+ EXPECT_FALSE(a.ConsumeFromEnd("foofoo"));
+ EXPECT_FALSE(a.ConsumeFromEnd("fo"));
+ EXPECT_EQ(a, "foo");
+}
+
+TEST(StringPiece, Contains) {
+ StringPiece a("abcdefg");
+ StringPiece b("abcd");
+ StringPiece c("efg");
+ StringPiece d("gh");
+ EXPECT_TRUE(a.contains(b));
+ EXPECT_TRUE(a.contains(c));
+ EXPECT_TRUE(!a.contains(d));
+}
+
+TEST(StringPiece, NULLInput) {
+ // we used to crash here, but now we don't.
+ StringPiece s(NULL);
+ EXPECT_EQ(s.data(), (const char*)NULL);
+ EXPECT_EQ(s.size(), 0);
+
+ s.set(NULL);
+ EXPECT_EQ(s.data(), (const char*)NULL);
+ EXPECT_EQ(s.size(), 0);
+
+ // .ToString() on a StringPiece with NULL should produce the empty string.
+ EXPECT_EQ("", s.ToString());
+ EXPECT_EQ("", s.as_string());
+}
+
+TEST(StringPiece, Comparisons2) {
+ StringPiece abc("abcdefghijklmnopqrstuvwxyz");
+
+ // check comparison operations on strings longer than 4 bytes.
+ EXPECT_EQ(abc, StringPiece("abcdefghijklmnopqrstuvwxyz"));
+ EXPECT_EQ(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxyz")), 0);
+
+ EXPECT_LT(abc, StringPiece("abcdefghijklmnopqrstuvwxzz"));
+ EXPECT_LT(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxzz")), 0);
+
+ EXPECT_GT(abc, StringPiece("abcdefghijklmnopqrstuvwxyy"));
+ EXPECT_GT(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxyy")), 0);
+
+ // starts_with
+ EXPECT_TRUE(abc.starts_with(abc));
+ EXPECT_TRUE(abc.starts_with("abcdefghijklm"));
+ EXPECT_TRUE(!abc.starts_with("abcdefguvwxyz"));
+
+ // ends_with
+ EXPECT_TRUE(abc.ends_with(abc));
+ EXPECT_TRUE(!abc.ends_with("abcdefguvwxyz"));
+ EXPECT_TRUE(abc.ends_with("nopqrstuvwxyz"));
+}
+
+TEST(ComparisonOpsTest, StringCompareNotAmbiguous) {
+ EXPECT_EQ("hello", string("hello"));
+ EXPECT_LT("hello", string("world"));
+}
+
+TEST(ComparisonOpsTest, HeterogenousStringPieceEquals) {
+ EXPECT_EQ(StringPiece("hello"), string("hello"));
+ EXPECT_EQ("hello", StringPiece("hello"));
+}
+
+TEST(FindOneCharTest, EdgeCases) {
+ StringPiece a("xxyyyxx");
+
+ // Set a = "xyyyx".
+ a.remove_prefix(1);
+ a.remove_suffix(1);
+
+ EXPECT_EQ(0, a.find('x'));
+ EXPECT_EQ(0, a.find('x', 0));
+ EXPECT_EQ(4, a.find('x', 1));
+ EXPECT_EQ(4, a.find('x', 4));
+ EXPECT_EQ(StringPiece::npos, a.find('x', 5));
+
+ EXPECT_EQ(4, a.rfind('x'));
+ EXPECT_EQ(4, a.rfind('x', 5));
+ EXPECT_EQ(4, a.rfind('x', 4));
+ EXPECT_EQ(0, a.rfind('x', 3));
+ EXPECT_EQ(0, a.rfind('x', 0));
+
+ // Set a = "yyy".
+ a.remove_prefix(1);
+ a.remove_suffix(1);
+
+ EXPECT_EQ(StringPiece::npos, a.find('x'));
+ EXPECT_EQ(StringPiece::npos, a.rfind('x'));
+}
+
+#ifndef NDEBUG
+TEST(NonNegativeLenTest, NonNegativeLen) {
+ EXPECT_DEATH(StringPiece("xyz", -1), "len >= 0");
+}
+#endif // ndef DEBUG
+
+} // namespace
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
index 86d45685..8442f2ce 100644
--- a/src/google/protobuf/stubs/strutil.cc
+++ b/src/google/protobuf/stubs/strutil.cc
@@ -31,6 +31,8 @@
// from google3/strings/strutil.cc
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/mathlimits.h>
+
#include <errno.h>
#include <float.h> // FLT_DIG and DBL_DIG
#include <limits>
@@ -38,6 +40,8 @@
#include <stdio.h>
#include <iterator>
+#include <google/protobuf/stubs/stl_util.h>
+
#ifdef _WIN32
// MSVC has only _snprintf, not snprintf.
//
@@ -55,11 +59,6 @@
namespace google {
namespace protobuf {
-inline bool IsNaN(double value) {
- // NaN is never equal to anything, even itself.
- return value != value;
-}
-
// These are defined as macros on some platforms. #undef them so that we can
// redefine them.
#undef isxdigit
@@ -309,17 +308,6 @@ void JoinStrings(const vector<string>& components,
#define IS_OCTAL_DIGIT(c) (((c) >= '0') && ((c) <= '7'))
-inline int hex_digit_to_int(char c) {
- /* Assume ASCII. */
- assert('0' == 0x30 && 'A' == 0x41 && 'a' == 0x61);
- assert(isxdigit(c));
- int x = static_cast<unsigned char>(c);
- if (x > '9') {
- x += 9;
- }
- return x & 0xf;
-}
-
// Protocol buffers doesn't ever care about errors, but I don't want to remove
// the code.
#define LOG_STRING(LEVEL, VECTOR) GOOGLE_LOG_IF(LEVEL, false)
@@ -652,14 +640,15 @@ inline bool safe_parse_sign(string* text /*inout*/,
return true;
}
-inline bool safe_parse_positive_int(
- string text, int32* value_p) {
+template<typename IntType>
+bool safe_parse_positive_int(
+ string text, IntType* value_p) {
int base = 10;
- int32 value = 0;
- const int32 vmax = std::numeric_limits<int32>::max();
+ IntType value = 0;
+ const IntType vmax = std::numeric_limits<IntType>::max();
assert(vmax > 0);
assert(vmax >= base);
- const int32 vmax_over_base = vmax / base;
+ const IntType vmax_over_base = vmax / base;
const char* start = text.data();
const char* end = start + text.size();
// loop over digits
@@ -685,14 +674,15 @@ inline bool safe_parse_positive_int(
return true;
}
-inline bool safe_parse_negative_int(
- string text, int32* value_p) {
+template<typename IntType>
+bool safe_parse_negative_int(
+ const string& text, IntType* value_p) {
int base = 10;
- int32 value = 0;
- const int32 vmin = std::numeric_limits<int32>::min();
+ IntType value = 0;
+ const IntType vmin = std::numeric_limits<IntType>::min();
assert(vmin < 0);
assert(vmin <= 0 - base);
- int32 vmin_over_base = vmin / base;
+ IntType vmin_over_base = vmin / base;
// 2003 c++ standard [expr.mul]
// "... the sign of the remainder is implementation-defined."
// Although (vmin/base)*base + vmin%base is always vmin.
@@ -725,7 +715,8 @@ inline bool safe_parse_negative_int(
return true;
}
-bool safe_int(string text, int32* value_p) {
+template<typename IntType>
+bool safe_int_internal(string text, IntType* value_p) {
*value_p = 0;
bool negative;
if (!safe_parse_sign(&text, &negative)) {
@@ -738,6 +729,16 @@ bool safe_int(string text, int32* value_p) {
}
}
+template<typename IntType>
+bool safe_uint_internal(string text, IntType* value_p) {
+ *value_p = 0;
+ bool negative;
+ if (!safe_parse_sign(&text, &negative) || negative) {
+ return false;
+ }
+ return safe_parse_positive_int(text, value_p);
+}
+
// ----------------------------------------------------------------------
// FastIntToBuffer()
// FastInt64ToBuffer()
@@ -871,13 +872,6 @@ char *FastHex32ToBuffer(uint32 value, char* buffer) {
return InternalFastHexToBuffer(value, buffer, 8);
}
-static inline char* PlaceNum(char* p, int num, char prev_sep) {
- *p-- = '0' + num % 10;
- *p-- = '0' + num / 10;
- *p-- = prev_sep;
- return p;
-}
-
// ----------------------------------------------------------------------
// FastInt32ToBufferLeft()
// FastUInt32ToBufferLeft()
@@ -1205,7 +1199,7 @@ char* DoubleToBuffer(double value, char* buffer) {
} else if (value == -numeric_limits<double>::infinity()) {
strcpy(buffer, "-inf");
return buffer;
- } else if (IsNaN(value)) {
+ } else if (MathLimits<double>::IsNaN(value)) {
strcpy(buffer, "nan");
return buffer;
}
@@ -1236,6 +1230,41 @@ char* DoubleToBuffer(double value, char* buffer) {
return buffer;
}
+static int memcasecmp(const char *s1, const char *s2, size_t len) {
+ const unsigned char *us1 = reinterpret_cast<const unsigned char *>(s1);
+ const unsigned char *us2 = reinterpret_cast<const unsigned char *>(s2);
+
+ for ( int i = 0; i < len; i++ ) {
+ const int diff =
+ static_cast<int>(static_cast<unsigned char>(ascii_tolower(us1[i]))) -
+ static_cast<int>(static_cast<unsigned char>(ascii_tolower(us2[i])));
+ if (diff != 0) return diff;
+ }
+ return 0;
+}
+
+inline bool CaseEqual(StringPiece s1, StringPiece s2) {
+ if (s1.size() != s2.size()) return false;
+ return memcasecmp(s1.data(), s2.data(), s1.size()) == 0;
+}
+
+bool safe_strtob(StringPiece str, bool* value) {
+ GOOGLE_CHECK(value != NULL) << "NULL output boolean given.";
+ if (CaseEqual(str, "true") || CaseEqual(str, "t") ||
+ CaseEqual(str, "yes") || CaseEqual(str, "y") ||
+ CaseEqual(str, "1")) {
+ *value = true;
+ return true;
+ }
+ if (CaseEqual(str, "false") || CaseEqual(str, "f") ||
+ CaseEqual(str, "no") || CaseEqual(str, "n") ||
+ CaseEqual(str, "0")) {
+ *value = false;
+ return true;
+ }
+ return false;
+}
+
bool safe_strtof(const char* str, float* value) {
char* endptr;
errno = 0; // errno only gets set on errors
@@ -1247,6 +1276,34 @@ bool safe_strtof(const char* str, float* value) {
return *str != 0 && *endptr == 0 && errno == 0;
}
+bool safe_strtod(const char* str, double* value) {
+ char* endptr;
+ *value = strtod(str, &endptr);
+ if (endptr != str) {
+ while (ascii_isspace(*endptr)) ++endptr;
+ }
+ // Ignore range errors from strtod. The values it
+ // returns on underflow and overflow are the right
+ // fallback in a robust setting.
+ return *str != '\0' && *endptr == '\0';
+}
+
+bool safe_strto32(const string& str, int32* value) {
+ return safe_int_internal(str, value);
+}
+
+bool safe_strtou32(const string& str, uint32* value) {
+ return safe_uint_internal(str, value);
+}
+
+bool safe_strto64(const string& str, int64* value) {
+ return safe_int_internal(str, value);
+}
+
+bool safe_strtou64(const string& str, uint64* value) {
+ return safe_uint_internal(str, value);
+}
+
char* FloatToBuffer(float value, char* buffer) {
// FLT_DIG is 6 for IEEE-754 floats, which are used on almost all
// platforms these days. Just in case some system exists where FLT_DIG
@@ -1260,7 +1317,7 @@ char* FloatToBuffer(float value, char* buffer) {
} else if (value == -numeric_limits<double>::infinity()) {
strcpy(buffer, "-inf");
return buffer;
- } else if (IsNaN(value)) {
+ } else if (MathLimits<float>::IsNaN(value)) {
strcpy(buffer, "nan");
return buffer;
}
@@ -1285,22 +1342,209 @@ char* FloatToBuffer(float value, char* buffer) {
return buffer;
}
-string ToHex(uint64 num) {
- if (num == 0) {
- return string("0");
- }
+namespace strings {
- // Compute hex bytes in reverse order, writing to the back of the
- // buffer.
- char buf[16]; // No more than 16 hex digits needed.
- char* bufptr = buf + 16;
- static const char kHexChars[] = "0123456789abcdef";
- while (num != 0) {
- *--bufptr = kHexChars[num & 0xf];
- num >>= 4;
- }
+AlphaNum::AlphaNum(strings::Hex hex) {
+ char *const end = &digits[kFastToBufferSize];
+ char *writer = end;
+ uint64 value = hex.value;
+ uint64 width = hex.spec;
+ // We accomplish minimum width by OR'ing in 0x10000 to the user's value,
+ // where 0x10000 is the smallest hex number that is as wide as the user
+ // asked for.
+ uint64 mask = ((static_cast<uint64>(1) << (width - 1) * 4)) | value;
+ static const char hexdigits[] = "0123456789abcdef";
+ do {
+ *--writer = hexdigits[value & 0xF];
+ value >>= 4;
+ mask >>= 4;
+ } while (mask != 0);
+ piece_data_ = writer;
+ piece_size_ = end - writer;
+}
+
+} // namespace strings
+
+// ----------------------------------------------------------------------
+// StrCat()
+// This merges the given strings or integers, with no delimiter. This
+// is designed to be the fastest possible way to construct a string out
+// of a mix of raw C strings, C++ strings, and integer values.
+// ----------------------------------------------------------------------
+
+// Append is merely a version of memcpy that returns the address of the byte
+// after the area just overwritten. It comes in multiple flavors to minimize
+// call overhead.
+static char *Append1(char *out, const AlphaNum &x) {
+ memcpy(out, x.data(), x.size());
+ return out + x.size();
+}
+
+static char *Append2(char *out, const AlphaNum &x1, const AlphaNum &x2) {
+ memcpy(out, x1.data(), x1.size());
+ out += x1.size();
- return string(bufptr, buf + 16 - bufptr);
+ memcpy(out, x2.data(), x2.size());
+ return out + x2.size();
+}
+
+static char *Append4(char *out,
+ const AlphaNum &x1, const AlphaNum &x2,
+ const AlphaNum &x3, const AlphaNum &x4) {
+ memcpy(out, x1.data(), x1.size());
+ out += x1.size();
+
+ memcpy(out, x2.data(), x2.size());
+ out += x2.size();
+
+ memcpy(out, x3.data(), x3.size());
+ out += x3.size();
+
+ memcpy(out, x4.data(), x4.size());
+ return out + x4.size();
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b) {
+ string result;
+ result.resize(a.size() + b.size());
+ char *const begin = &*result.begin();
+ char *out = Append2(begin, a, b);
+ GOOGLE_DCHECK_EQ(out, begin + result.size());
+ return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) {
+ string result;
+ result.resize(a.size() + b.size() + c.size());
+ char *const begin = &*result.begin();
+ char *out = Append2(begin, a, b);
+ out = Append1(out, c);
+ GOOGLE_DCHECK_EQ(out, begin + result.size());
+ return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d) {
+ string result;
+ result.resize(a.size() + b.size() + c.size() + d.size());
+ char *const begin = &*result.begin();
+ char *out = Append4(begin, a, b, c, d);
+ GOOGLE_DCHECK_EQ(out, begin + result.size());
+ return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d, const AlphaNum &e) {
+ string result;
+ result.resize(a.size() + b.size() + c.size() + d.size() + e.size());
+ char *const begin = &*result.begin();
+ char *out = Append4(begin, a, b, c, d);
+ out = Append1(out, e);
+ GOOGLE_DCHECK_EQ(out, begin + result.size());
+ return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d, const AlphaNum &e, const AlphaNum &f) {
+ string result;
+ result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
+ f.size());
+ char *const begin = &*result.begin();
+ char *out = Append4(begin, a, b, c, d);
+ out = Append2(out, e, f);
+ GOOGLE_DCHECK_EQ(out, begin + result.size());
+ return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+ const AlphaNum &g) {
+ string result;
+ result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
+ f.size() + g.size());
+ char *const begin = &*result.begin();
+ char *out = Append4(begin, a, b, c, d);
+ out = Append2(out, e, f);
+ out = Append1(out, g);
+ GOOGLE_DCHECK_EQ(out, begin + result.size());
+ return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+ const AlphaNum &g, const AlphaNum &h) {
+ string result;
+ result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
+ f.size() + g.size() + h.size());
+ char *const begin = &*result.begin();
+ char *out = Append4(begin, a, b, c, d);
+ out = Append4(out, e, f, g, h);
+ GOOGLE_DCHECK_EQ(out, begin + result.size());
+ return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+ const AlphaNum &g, const AlphaNum &h, const AlphaNum &i) {
+ string result;
+ result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
+ f.size() + g.size() + h.size() + i.size());
+ char *const begin = &*result.begin();
+ char *out = Append4(begin, a, b, c, d);
+ out = Append4(out, e, f, g, h);
+ out = Append1(out, i);
+ GOOGLE_DCHECK_EQ(out, begin + result.size());
+ return result;
+}
+
+// It's possible to call StrAppend with a char * pointer that is partway into
+// the string we're appending to. However the results of this are random.
+// Therefore, check for this in debug mode. Use unsigned math so we only have
+// to do one comparison.
+#define GOOGLE_DCHECK_NO_OVERLAP(dest, src) \
+ GOOGLE_DCHECK_GT(uintptr_t((src).data() - (dest).data()), \
+ uintptr_t((dest).size()))
+
+void StrAppend(string *result, const AlphaNum &a) {
+ GOOGLE_DCHECK_NO_OVERLAP(*result, a);
+ result->append(a.data(), a.size());
+}
+
+void StrAppend(string *result, const AlphaNum &a, const AlphaNum &b) {
+ GOOGLE_DCHECK_NO_OVERLAP(*result, a);
+ GOOGLE_DCHECK_NO_OVERLAP(*result, b);
+ string::size_type old_size = result->size();
+ result->resize(old_size + a.size() + b.size());
+ char *const begin = &*result->begin();
+ char *out = Append2(begin + old_size, a, b);
+ GOOGLE_DCHECK_EQ(out, begin + result->size());
+}
+
+void StrAppend(string *result,
+ const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) {
+ GOOGLE_DCHECK_NO_OVERLAP(*result, a);
+ GOOGLE_DCHECK_NO_OVERLAP(*result, b);
+ GOOGLE_DCHECK_NO_OVERLAP(*result, c);
+ string::size_type old_size = result->size();
+ result->resize(old_size + a.size() + b.size() + c.size());
+ char *const begin = &*result->begin();
+ char *out = Append2(begin + old_size, a, b);
+ out = Append1(out, c);
+ GOOGLE_DCHECK_EQ(out, begin + result->size());
+}
+
+void StrAppend(string *result,
+ const AlphaNum &a, const AlphaNum &b,
+ const AlphaNum &c, const AlphaNum &d) {
+ GOOGLE_DCHECK_NO_OVERLAP(*result, a);
+ GOOGLE_DCHECK_NO_OVERLAP(*result, b);
+ GOOGLE_DCHECK_NO_OVERLAP(*result, c);
+ GOOGLE_DCHECK_NO_OVERLAP(*result, d);
+ string::size_type old_size = result->size();
+ result->resize(old_size + a.size() + b.size() + c.size() + d.size());
+ char *const begin = &*result->begin();
+ char *out = Append4(begin + old_size, a, b, c, d);
+ GOOGLE_DCHECK_EQ(out, begin + result->size());
}
int GlobalReplaceSubstring(const string& substring,
@@ -1331,5 +1575,661 @@ int GlobalReplaceSubstring(const string& substring,
return num_replacements;
}
+int CalculateBase64EscapedLen(int input_len, bool do_padding) {
+ // Base64 encodes three bytes of input at a time. If the input is not
+ // divisible by three, we pad as appropriate.
+ //
+ // (from http://tools.ietf.org/html/rfc3548)
+ // Special processing is performed if fewer than 24 bits are available
+ // at the end of the data being encoded. A full encoding quantum is
+ // always completed at the end of a quantity. When fewer than 24 input
+ // bits are available in an input group, zero bits are added (on the
+ // right) to form an integral number of 6-bit groups. Padding at the
+ // end of the data is performed using the '=' character. Since all base
+ // 64 input is an integral number of octets, only the following cases
+ // can arise:
+
+
+ // Base64 encodes each three bytes of input into four bytes of output.
+ int len = (input_len / 3) * 4;
+
+ if (input_len % 3 == 0) {
+ // (from http://tools.ietf.org/html/rfc3548)
+ // (1) the final quantum of encoding input is an integral multiple of 24
+ // bits; here, the final unit of encoded output will be an integral
+ // multiple of 4 characters with no "=" padding,
+ } else if (input_len % 3 == 1) {
+ // (from http://tools.ietf.org/html/rfc3548)
+ // (2) the final quantum of encoding input is exactly 8 bits; here, the
+ // final unit of encoded output will be two characters followed by two
+ // "=" padding characters, or
+ len += 2;
+ if (do_padding) {
+ len += 2;
+ }
+ } else { // (input_len % 3 == 2)
+ // (from http://tools.ietf.org/html/rfc3548)
+ // (3) the final quantum of encoding input is exactly 16 bits; here, the
+ // final unit of encoded output will be three characters followed by one
+ // "=" padding character.
+ len += 3;
+ if (do_padding) {
+ len += 1;
+ }
+ }
+
+ assert(len >= input_len); // make sure we didn't overflow
+ return len;
+}
+
+// Base64Escape does padding, so this calculation includes padding.
+int CalculateBase64EscapedLen(int input_len) {
+ return CalculateBase64EscapedLen(input_len, true);
+}
+
+// ----------------------------------------------------------------------
+// int Base64Unescape() - base64 decoder
+// int Base64Escape() - base64 encoder
+// int WebSafeBase64Unescape() - Google's variation of base64 decoder
+// int WebSafeBase64Escape() - Google's variation of base64 encoder
+//
+// Check out
+// http://tools.ietf.org/html/rfc2045 for formal description, but what we
+// care about is that...
+// Take the encoded stuff in groups of 4 characters and turn each
+// character into a code 0 to 63 thus:
+// A-Z map to 0 to 25
+// a-z map to 26 to 51
+// 0-9 map to 52 to 61
+// +(- for WebSafe) maps to 62
+// /(_ for WebSafe) maps to 63
+// There will be four numbers, all less than 64 which can be represented
+// by a 6 digit binary number (aaaaaa, bbbbbb, cccccc, dddddd respectively).
+// Arrange the 6 digit binary numbers into three bytes as such:
+// aaaaaabb bbbbcccc ccdddddd
+// Equals signs (one or two) are used at the end of the encoded block to
+// indicate that the text was not an integer multiple of three bytes long.
+// ----------------------------------------------------------------------
+
+int Base64UnescapeInternal(const char *src_param, int szsrc,
+ char *dest, int szdest,
+ const signed char* unbase64) {
+ static const char kPad64Equals = '=';
+ static const char kPad64Dot = '.';
+
+ int decode = 0;
+ int destidx = 0;
+ int state = 0;
+ unsigned int ch = 0;
+ unsigned int temp = 0;
+
+ // If "char" is signed by default, using *src as an array index results in
+ // accessing negative array elements. Treat the input as a pointer to
+ // unsigned char to avoid this.
+ const unsigned char *src = reinterpret_cast<const unsigned char*>(src_param);
+
+ // The GET_INPUT macro gets the next input character, skipping
+ // over any whitespace, and stopping when we reach the end of the
+ // string or when we read any non-data character. The arguments are
+ // an arbitrary identifier (used as a label for goto) and the number
+ // of data bytes that must remain in the input to avoid aborting the
+ // loop.
+#define GET_INPUT(label, remain) \
+ label: \
+ --szsrc; \
+ ch = *src++; \
+ decode = unbase64[ch]; \
+ if (decode < 0) { \
+ if (ascii_isspace(ch) && szsrc >= remain) \
+ goto label; \
+ state = 4 - remain; \
+ break; \
+ }
+
+ // if dest is null, we're just checking to see if it's legal input
+ // rather than producing output. (I suspect this could just be done
+ // with a regexp...). We duplicate the loop so this test can be
+ // outside it instead of in every iteration.
+
+ if (dest) {
+ // This loop consumes 4 input bytes and produces 3 output bytes
+ // per iteration. We can't know at the start that there is enough
+ // data left in the string for a full iteration, so the loop may
+ // break out in the middle; if so 'state' will be set to the
+ // number of input bytes read.
+
+ while (szsrc >= 4) {
+ // We'll start by optimistically assuming that the next four
+ // bytes of the string (src[0..3]) are four good data bytes
+ // (that is, no nulls, whitespace, padding chars, or illegal
+ // chars). We need to test src[0..2] for nulls individually
+ // before constructing temp to preserve the property that we
+ // never read past a null in the string (no matter how long
+ // szsrc claims the string is).
+
+ if (!src[0] || !src[1] || !src[2] ||
+ (temp = ((unsigned(unbase64[src[0]]) << 18) |
+ (unsigned(unbase64[src[1]]) << 12) |
+ (unsigned(unbase64[src[2]]) << 6) |
+ (unsigned(unbase64[src[3]])))) & 0x80000000) {
+ // Iff any of those four characters was bad (null, illegal,
+ // whitespace, padding), then temp's high bit will be set
+ // (because unbase64[] is -1 for all bad characters).
+ //
+ // We'll back up and resort to the slower decoder, which knows
+ // how to handle those cases.
+
+ GET_INPUT(first, 4);
+ temp = decode;
+ GET_INPUT(second, 3);
+ temp = (temp << 6) | decode;
+ GET_INPUT(third, 2);
+ temp = (temp << 6) | decode;
+ GET_INPUT(fourth, 1);
+ temp = (temp << 6) | decode;
+ } else {
+ // We really did have four good data bytes, so advance four
+ // characters in the string.
+
+ szsrc -= 4;
+ src += 4;
+ decode = -1;
+ ch = '\0';
+ }
+
+ // temp has 24 bits of input, so write that out as three bytes.
+
+ if (destidx+3 > szdest) return -1;
+ dest[destidx+2] = temp;
+ temp >>= 8;
+ dest[destidx+1] = temp;
+ temp >>= 8;
+ dest[destidx] = temp;
+ destidx += 3;
+ }
+ } else {
+ while (szsrc >= 4) {
+ if (!src[0] || !src[1] || !src[2] ||
+ (temp = ((unsigned(unbase64[src[0]]) << 18) |
+ (unsigned(unbase64[src[1]]) << 12) |
+ (unsigned(unbase64[src[2]]) << 6) |
+ (unsigned(unbase64[src[3]])))) & 0x80000000) {
+ GET_INPUT(first_no_dest, 4);
+ GET_INPUT(second_no_dest, 3);
+ GET_INPUT(third_no_dest, 2);
+ GET_INPUT(fourth_no_dest, 1);
+ } else {
+ szsrc -= 4;
+ src += 4;
+ decode = -1;
+ ch = '\0';
+ }
+ destidx += 3;
+ }
+ }
+
+#undef GET_INPUT
+
+ // if the loop terminated because we read a bad character, return
+ // now.
+ if (decode < 0 && ch != '\0' &&
+ ch != kPad64Equals && ch != kPad64Dot && !ascii_isspace(ch))
+ return -1;
+
+ if (ch == kPad64Equals || ch == kPad64Dot) {
+ // if we stopped by hitting an '=' or '.', un-read that character -- we'll
+ // look at it again when we count to check for the proper number of
+ // equals signs at the end.
+ ++szsrc;
+ --src;
+ } else {
+ // This loop consumes 1 input byte per iteration. It's used to
+ // clean up the 0-3 input bytes remaining when the first, faster
+ // loop finishes. 'temp' contains the data from 'state' input
+ // characters read by the first loop.
+ while (szsrc > 0) {
+ --szsrc;
+ ch = *src++;
+ decode = unbase64[ch];
+ if (decode < 0) {
+ if (ascii_isspace(ch)) {
+ continue;
+ } else if (ch == '\0') {
+ break;
+ } else if (ch == kPad64Equals || ch == kPad64Dot) {
+ // back up one character; we'll read it again when we check
+ // for the correct number of pad characters at the end.
+ ++szsrc;
+ --src;
+ break;
+ } else {
+ return -1;
+ }
+ }
+
+ // Each input character gives us six bits of output.
+ temp = (temp << 6) | decode;
+ ++state;
+ if (state == 4) {
+ // If we've accumulated 24 bits of output, write that out as
+ // three bytes.
+ if (dest) {
+ if (destidx+3 > szdest) return -1;
+ dest[destidx+2] = temp;
+ temp >>= 8;
+ dest[destidx+1] = temp;
+ temp >>= 8;
+ dest[destidx] = temp;
+ }
+ destidx += 3;
+ state = 0;
+ temp = 0;
+ }
+ }
+ }
+
+ // Process the leftover data contained in 'temp' at the end of the input.
+ int expected_equals = 0;
+ switch (state) {
+ case 0:
+ // Nothing left over; output is a multiple of 3 bytes.
+ break;
+
+ case 1:
+ // Bad input; we have 6 bits left over.
+ return -1;
+
+ case 2:
+ // Produce one more output byte from the 12 input bits we have left.
+ if (dest) {
+ if (destidx+1 > szdest) return -1;
+ temp >>= 4;
+ dest[destidx] = temp;
+ }
+ ++destidx;
+ expected_equals = 2;
+ break;
+
+ case 3:
+ // Produce two more output bytes from the 18 input bits we have left.
+ if (dest) {
+ if (destidx+2 > szdest) return -1;
+ temp >>= 2;
+ dest[destidx+1] = temp;
+ temp >>= 8;
+ dest[destidx] = temp;
+ }
+ destidx += 2;
+ expected_equals = 1;
+ break;
+
+ default:
+ // state should have no other values at this point.
+ GOOGLE_LOG(FATAL) << "This can't happen; base64 decoder state = " << state;
+ }
+
+ // The remainder of the string should be all whitespace, mixed with
+ // exactly 0 equals signs, or exactly 'expected_equals' equals
+ // signs. (Always accepting 0 equals signs is a google extension
+ // not covered in the RFC, as is accepting dot as the pad character.)
+
+ int equals = 0;
+ while (szsrc > 0 && *src) {
+ if (*src == kPad64Equals || *src == kPad64Dot)
+ ++equals;
+ else if (!ascii_isspace(*src))
+ return -1;
+ --szsrc;
+ ++src;
+ }
+
+ return (equals == 0 || equals == expected_equals) ? destidx : -1;
+}
+
+// The arrays below were generated by the following code
+// #include <sys/time.h>
+// #include <stdlib.h>
+// #include <string.h>
+// main()
+// {
+// static const char Base64[] =
+// "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+// char *pos;
+// int idx, i, j;
+// printf(" ");
+// for (i = 0; i < 255; i += 8) {
+// for (j = i; j < i + 8; j++) {
+// pos = strchr(Base64, j);
+// if ((pos == NULL) || (j == 0))
+// idx = -1;
+// else
+// idx = pos - Base64;
+// if (idx == -1)
+// printf(" %2d, ", idx);
+// else
+// printf(" %2d/*%c*/,", idx, j);
+// }
+// printf("\n ");
+// }
+// }
+//
+// where the value of "Base64[]" was replaced by one of the base-64 conversion
+// tables from the functions below.
+static const signed char kUnBase64[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */,
+ 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
+ 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
+ -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
+ 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
+ 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
+ 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1,
+ -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
+ 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
+ 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
+ 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1
+};
+static const signed char kUnWebSafeBase64[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 62/*-*/, -1, -1,
+ 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
+ 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
+ -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
+ 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
+ 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
+ 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, 63/*_*/,
+ -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
+ 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
+ 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
+ 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+int WebSafeBase64Unescape(const char *src, int szsrc, char *dest, int szdest) {
+ return Base64UnescapeInternal(src, szsrc, dest, szdest, kUnWebSafeBase64);
+}
+
+static bool Base64UnescapeInternal(const char* src, int slen, string* dest,
+ const signed char* unbase64) {
+ // Determine the size of the output string. Base64 encodes every 3 bytes into
+ // 4 characters. any leftover chars are added directly for good measure.
+ // This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548
+ const int dest_len = 3 * (slen / 4) + (slen % 4);
+
+ dest->resize(dest_len);
+
+ // We are getting the destination buffer by getting the beginning of the
+ // string and converting it into a char *.
+ const int len = Base64UnescapeInternal(src, slen, string_as_array(dest),
+ dest_len, unbase64);
+ if (len < 0) {
+ dest->clear();
+ return false;
+ }
+
+ // could be shorter if there was padding
+ GOOGLE_DCHECK_LE(len, dest_len);
+ dest->erase(len);
+
+ return true;
+}
+
+bool Base64Unescape(StringPiece src, string* dest) {
+ return Base64UnescapeInternal(src.data(), src.size(), dest, kUnBase64);
+}
+
+bool WebSafeBase64Unescape(StringPiece src, string* dest) {
+ return Base64UnescapeInternal(src.data(), src.size(), dest, kUnWebSafeBase64);
+}
+
+int Base64EscapeInternal(const unsigned char *src, int szsrc,
+ char *dest, int szdest, const char *base64,
+ bool do_padding) {
+ static const char kPad64 = '=';
+
+ if (szsrc <= 0) return 0;
+
+ if (szsrc * 4 > szdest * 3) return 0;
+
+ char *cur_dest = dest;
+ const unsigned char *cur_src = src;
+
+ char *limit_dest = dest + szdest;
+ const unsigned char *limit_src = src + szsrc;
+
+ // Three bytes of data encodes to four characters of cyphertext.
+ // So we can pump through three-byte chunks atomically.
+ while (cur_src < limit_src - 3) { // keep going as long as we have >= 32 bits
+ uint32 in = BigEndian::Load32(cur_src) >> 8;
+
+ cur_dest[0] = base64[in >> 18];
+ in &= 0x3FFFF;
+ cur_dest[1] = base64[in >> 12];
+ in &= 0xFFF;
+ cur_dest[2] = base64[in >> 6];
+ in &= 0x3F;
+ cur_dest[3] = base64[in];
+
+ cur_dest += 4;
+ cur_src += 3;
+ }
+ // To save time, we didn't update szdest or szsrc in the loop. So do it now.
+ szdest = limit_dest - cur_dest;
+ szsrc = limit_src - cur_src;
+
+ /* now deal with the tail (<=3 bytes) */
+ switch (szsrc) {
+ case 0:
+ // Nothing left; nothing more to do.
+ break;
+ case 1: {
+ // One byte left: this encodes to two characters, and (optionally)
+ // two pad characters to round out the four-character cypherblock.
+ if ((szdest -= 2) < 0) return 0;
+ uint32 in = cur_src[0];
+ cur_dest[0] = base64[in >> 2];
+ in &= 0x3;
+ cur_dest[1] = base64[in << 4];
+ cur_dest += 2;
+ if (do_padding) {
+ if ((szdest -= 2) < 0) return 0;
+ cur_dest[0] = kPad64;
+ cur_dest[1] = kPad64;
+ cur_dest += 2;
+ }
+ break;
+ }
+ case 2: {
+ // Two bytes left: this encodes to three characters, and (optionally)
+ // one pad character to round out the four-character cypherblock.
+ if ((szdest -= 3) < 0) return 0;
+ uint32 in = BigEndian::Load16(cur_src);
+ cur_dest[0] = base64[in >> 10];
+ in &= 0x3FF;
+ cur_dest[1] = base64[in >> 4];
+ in &= 0x00F;
+ cur_dest[2] = base64[in << 2];
+ cur_dest += 3;
+ if (do_padding) {
+ if ((szdest -= 1) < 0) return 0;
+ cur_dest[0] = kPad64;
+ cur_dest += 1;
+ }
+ break;
+ }
+ case 3: {
+ // Three bytes left: same as in the big loop above. We can't do this in
+ // the loop because the loop above always reads 4 bytes, and the fourth
+ // byte is past the end of the input.
+ if ((szdest -= 4) < 0) return 0;
+ uint32 in = (cur_src[0] << 16) + BigEndian::Load16(cur_src + 1);
+ cur_dest[0] = base64[in >> 18];
+ in &= 0x3FFFF;
+ cur_dest[1] = base64[in >> 12];
+ in &= 0xFFF;
+ cur_dest[2] = base64[in >> 6];
+ in &= 0x3F;
+ cur_dest[3] = base64[in];
+ cur_dest += 4;
+ break;
+ }
+ default:
+ // Should not be reached: blocks of 4 bytes are handled
+ // in the while loop before this switch statement.
+ GOOGLE_LOG(FATAL) << "Logic problem? szsrc = " << szsrc;
+ break;
+ }
+ return (cur_dest - dest);
+}
+
+static const char kBase64Chars[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static const char kWebSafeBase64Chars[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+
+int Base64Escape(const unsigned char *src, int szsrc, char *dest, int szdest) {
+ return Base64EscapeInternal(src, szsrc, dest, szdest, kBase64Chars, true);
+}
+int WebSafeBase64Escape(const unsigned char *src, int szsrc, char *dest,
+ int szdest, bool do_padding) {
+ return Base64EscapeInternal(src, szsrc, dest, szdest,
+ kWebSafeBase64Chars, do_padding);
+}
+
+void Base64EscapeInternal(const unsigned char* src, int szsrc,
+ string* dest, bool do_padding,
+ const char* base64_chars) {
+ const int calc_escaped_size =
+ CalculateBase64EscapedLen(szsrc, do_padding);
+ dest->resize(calc_escaped_size);
+ const int escaped_len = Base64EscapeInternal(src, szsrc,
+ string_as_array(dest),
+ dest->size(),
+ base64_chars,
+ do_padding);
+ GOOGLE_DCHECK_EQ(calc_escaped_size, escaped_len);
+ dest->erase(escaped_len);
+}
+
+void Base64Escape(const unsigned char *src, int szsrc,
+ string* dest, bool do_padding) {
+ Base64EscapeInternal(src, szsrc, dest, do_padding, kBase64Chars);
+}
+
+void WebSafeBase64Escape(const unsigned char *src, int szsrc,
+ string *dest, bool do_padding) {
+ Base64EscapeInternal(src, szsrc, dest, do_padding, kWebSafeBase64Chars);
+}
+
+void Base64Escape(StringPiece src, string* dest) {
+ Base64Escape(reinterpret_cast<const unsigned char*>(src.data()),
+ src.size(), dest, true);
+}
+
+void WebSafeBase64Escape(StringPiece src, string* dest) {
+ WebSafeBase64Escape(reinterpret_cast<const unsigned char*>(src.data()),
+ src.size(), dest, false);
+}
+
+void WebSafeBase64EscapeWithPadding(StringPiece src, string* dest) {
+ WebSafeBase64Escape(reinterpret_cast<const unsigned char*>(src.data()),
+ src.size(), dest, true);
+}
+
+// Helper to append a Unicode code point to a string as UTF8, without bringing
+// in any external dependencies.
+int EncodeAsUTF8Char(uint32 code_point, char* output) {
+ uint32 tmp = 0;
+ int len = 0;
+ if (code_point <= 0x7f) {
+ tmp = code_point;
+ len = 1;
+ } else if (code_point <= 0x07ff) {
+ tmp = 0x0000c080 |
+ ((code_point & 0x07c0) << 2) |
+ (code_point & 0x003f);
+ len = 2;
+ } else if (code_point <= 0xffff) {
+ tmp = 0x00e08080 |
+ ((code_point & 0xf000) << 4) |
+ ((code_point & 0x0fc0) << 2) |
+ (code_point & 0x003f);
+ len = 3;
+ } else {
+ // UTF-16 is only defined for code points up to 0x10FFFF, and UTF-8 is
+ // normally only defined up to there as well.
+ tmp = 0xf0808080 |
+ ((code_point & 0x1c0000) << 6) |
+ ((code_point & 0x03f000) << 4) |
+ ((code_point & 0x000fc0) << 2) |
+ (code_point & 0x003f);
+ len = 4;
+ }
+ tmp = ghtonl(tmp);
+ memcpy(output, reinterpret_cast<const char*>(&tmp) + sizeof(tmp) - len, len);
+ return len;
+}
+
+// Table of UTF-8 character lengths, based on first byte
+static const unsigned char kUTF8LenTbl[256] = {
+ 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
+
+ 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,
+ 3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4
+};
+
+// Return length of a single UTF-8 source character
+int UTF8FirstLetterNumBytes(const char* src, int len) {
+ if (len == 0) {
+ return 0;
+ }
+ return kUTF8LenTbl[*reinterpret_cast<const uint8*>(src)];
+}
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
index f2e1a944..b22066b6 100644
--- a/src/google/protobuf/stubs/strutil.h
+++ b/src/google/protobuf/stubs/strutil.h
@@ -36,6 +36,7 @@
#include <stdlib.h>
#include <vector>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
namespace google {
namespace protobuf {
@@ -72,7 +73,33 @@ inline bool ascii_isdigit(char c) {
}
inline bool ascii_isspace(char c) {
- return c == ' ';
+ return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' ||
+ c == '\r';
+}
+
+inline bool ascii_isupper(char c) {
+ return c >= 'A' && c <= 'Z';
+}
+
+inline bool ascii_islower(char c) {
+ return c >= 'a' && c <= 'z';
+}
+
+inline char ascii_toupper(char c) {
+ return ascii_islower(c) ? c - ('a' - 'A') : c;
+}
+
+inline char ascii_tolower(char c) {
+ return ascii_isupper(c) ? c + ('a' - 'A') : c;
+}
+
+inline int hex_digit_to_int(char c) {
+ /* Assume ASCII. */
+ int x = static_cast<unsigned char>(c);
+ if (x > '9') {
+ x += 9;
+ }
+ return x & 0xf;
}
// ----------------------------------------------------------------------
@@ -360,12 +387,59 @@ inline uint64 strtou64(const char *nptr, char **endptr, int base) {
}
// ----------------------------------------------------------------------
+// safe_strtob()
// safe_strto32()
+// safe_strtou32()
+// safe_strto64()
+// safe_strtou64()
+// safe_strtof()
+// safe_strtod()
// ----------------------------------------------------------------------
-LIBPROTOBUF_EXPORT bool safe_int(string text, int32* value_p);
+LIBPROTOBUF_EXPORT bool safe_strtob(StringPiece str, bool* value);
+
+LIBPROTOBUF_EXPORT bool safe_strto32(const string& str, int32* value);
+LIBPROTOBUF_EXPORT bool safe_strtou32(const string& str, uint32* value);
+inline bool safe_strto32(const char* str, int32* value) {
+ return safe_strto32(string(str), value);
+}
+inline bool safe_strto32(StringPiece str, int32* value) {
+ return safe_strto32(str.ToString(), value);
+}
+inline bool safe_strtou32(const char* str, uint32* value) {
+ return safe_strtou32(string(str), value);
+}
+inline bool safe_strtou32(StringPiece str, uint32* value) {
+ return safe_strtou32(str.ToString(), value);
+}
-inline bool safe_strto32(string text, int32* value) {
- return safe_int(text, value);
+LIBPROTOBUF_EXPORT bool safe_strto64(const string& str, int64* value);
+LIBPROTOBUF_EXPORT bool safe_strtou64(const string& str, uint64* value);
+inline bool safe_strto64(const char* str, int64* value) {
+ return safe_strto64(string(str), value);
+}
+inline bool safe_strto64(StringPiece str, int64* value) {
+ return safe_strto64(str.ToString(), value);
+}
+inline bool safe_strtou64(const char* str, uint64* value) {
+ return safe_strtou64(string(str), value);
+}
+inline bool safe_strtou64(StringPiece str, uint64* value) {
+ return safe_strtou64(str.ToString(), value);
+}
+
+LIBPROTOBUF_EXPORT bool safe_strtof(const char* str, float* value);
+LIBPROTOBUF_EXPORT bool safe_strtod(const char* str, double* value);
+inline bool safe_strtof(const string& str, float* value) {
+ return safe_strtof(str.c_str(), value);
+}
+inline bool safe_strtod(const string& str, double* value) {
+ return safe_strtod(str.c_str(), value);
+}
+inline bool safe_strtof(StringPiece str, float* value) {
+ return safe_strtof(str.ToString(), value);
+}
+inline bool safe_strtod(StringPiece str, double* value) {
+ return safe_strtod(str.ToString(), value);
}
// ----------------------------------------------------------------------
@@ -451,6 +525,10 @@ inline char* FastUInt64ToBuffer(uint64 i, char* buffer) {
return buffer;
}
+inline string SimpleBtoa(bool value) {
+ return value ? "true" : "false";
+}
+
// ----------------------------------------------------------------------
// SimpleItoa()
// Description: converts an integer to a string.
@@ -495,57 +573,182 @@ LIBPROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer);
static const int kDoubleToBufferSize = 32;
static const int kFloatToBufferSize = 24;
-// ----------------------------------------------------------------------
-// ToString() are internal help methods used in StrCat() and Join()
-// ----------------------------------------------------------------------
-namespace internal {
-inline string ToString(int i) {
- return SimpleItoa(i);
-}
+namespace strings {
-inline string ToString(string a) {
- return a;
-}
-} // namespace internal
+enum PadSpec {
+ NO_PAD = 1,
+ ZERO_PAD_2,
+ ZERO_PAD_3,
+ ZERO_PAD_4,
+ ZERO_PAD_5,
+ ZERO_PAD_6,
+ ZERO_PAD_7,
+ ZERO_PAD_8,
+ ZERO_PAD_9,
+ ZERO_PAD_10,
+ ZERO_PAD_11,
+ ZERO_PAD_12,
+ ZERO_PAD_13,
+ ZERO_PAD_14,
+ ZERO_PAD_15,
+ ZERO_PAD_16,
+};
+
+struct Hex {
+ uint64 value;
+ enum PadSpec spec;
+ template <class Int>
+ explicit Hex(Int v, PadSpec s = NO_PAD)
+ : spec(s) {
+ // Prevent sign-extension by casting integers to
+ // their unsigned counterparts.
+#ifdef LANG_CXX11
+ static_assert(
+ sizeof(v) == 1 || sizeof(v) == 2 || sizeof(v) == 4 || sizeof(v) == 8,
+ "Unknown integer type");
+#endif
+ value = sizeof(v) == 1 ? static_cast<uint8>(v)
+ : sizeof(v) == 2 ? static_cast<uint16>(v)
+ : sizeof(v) == 4 ? static_cast<uint32>(v)
+ : static_cast<uint64>(v);
+ }
+};
-// ----------------------------------------------------------------------
-// StrCat()
-// These methods join some strings together.
-// ----------------------------------------------------------------------
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7>
-string StrCat(
- const T1& a, const T2& b, const T3& c, const T4& d, const T5& e,
- const T6& f, const T7& g) {
- return internal::ToString(a) + internal::ToString(b) +
- internal::ToString(c) + internal::ToString(d) + internal::ToString(e) +
- internal::ToString(f) + internal::ToString(g);
-}
+struct LIBPROTOBUF_EXPORT AlphaNum {
+ const char *piece_data_; // move these to string_ref eventually
+ size_t piece_size_; // move these to string_ref eventually
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-string StrCat(
- const T1& a, const T2& b, const T3& c, const T4& d, const T5& e) {
- return internal::ToString(a) + internal::ToString(b) +
- internal::ToString(c) + internal::ToString(d) + internal::ToString(e);
-}
+ char digits[kFastToBufferSize];
-template <typename T1, typename T2, typename T3, typename T4>
-string StrCat(
- const T1& a, const T2& b, const T3& c, const T4& d) {
- return internal::ToString(a) + internal::ToString(b) +
- internal::ToString(c) + internal::ToString(d);
-}
+ // No bool ctor -- bools convert to an integral type.
+ // A bool ctor would also convert incoming pointers (bletch).
-template <typename T1, typename T2, typename T3>
-string StrCat(const T1& a, const T2& b, const T3& c) {
- return internal::ToString(a) + internal::ToString(b) +
- internal::ToString(c);
-}
+ AlphaNum(int32 i32)
+ : piece_data_(digits),
+ piece_size_(FastInt32ToBufferLeft(i32, digits) - &digits[0]) {}
+ AlphaNum(uint32 u32)
+ : piece_data_(digits),
+ piece_size_(FastUInt32ToBufferLeft(u32, digits) - &digits[0]) {}
+ AlphaNum(int64 i64)
+ : piece_data_(digits),
+ piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {}
+ AlphaNum(uint64 u64)
+ : piece_data_(digits),
+ piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {}
-template <typename T1, typename T2>
-string StrCat(const T1& a, const T2& b) {
- return internal::ToString(a) + internal::ToString(b);
-}
+ AlphaNum(float f)
+ : piece_data_(digits), piece_size_(strlen(FloatToBuffer(f, digits))) {}
+ AlphaNum(double f)
+ : piece_data_(digits), piece_size_(strlen(DoubleToBuffer(f, digits))) {}
+
+ AlphaNum(Hex hex);
+
+ AlphaNum(const char* c_str)
+ : piece_data_(c_str), piece_size_(strlen(c_str)) {}
+ // TODO: Add a string_ref constructor, eventually
+ // AlphaNum(const StringPiece &pc) : piece(pc) {}
+
+ AlphaNum(const string& str)
+ : piece_data_(str.data()), piece_size_(str.size()) {}
+
+ AlphaNum(StringPiece str)
+ : piece_data_(str.data()), piece_size_(str.size()) {}
+
+ size_t size() const { return piece_size_; }
+ const char *data() const { return piece_data_; }
+
+ private:
+ // Use ":" not ':'
+ AlphaNum(char c); // NOLINT(runtime/explicit)
+
+ // Disallow copy and assign.
+ AlphaNum(const AlphaNum&);
+ void operator=(const AlphaNum&);
+};
+
+} // namespace strings
+
+using strings::AlphaNum;
+
+// ----------------------------------------------------------------------
+// StrCat()
+// This merges the given strings or numbers, with no delimiter. This
+// is designed to be the fastest possible way to construct a string out
+// of a mix of raw C strings, strings, bool values,
+// and numeric values.
+//
+// Don't use this for user-visible strings. The localization process
+// works poorly on strings built up out of fragments.
+//
+// For clarity and performance, don't use StrCat when appending to a
+// string. In particular, avoid using any of these (anti-)patterns:
+// str.append(StrCat(...)
+// str += StrCat(...)
+// str = StrCat(str, ...)
+// where the last is the worse, with the potential to change a loop
+// from a linear time operation with O(1) dynamic allocations into a
+// quadratic time operation with O(n) dynamic allocations. StrAppend
+// is a better choice than any of the above, subject to the restriction
+// of StrAppend(&str, a, b, c, ...) that none of the a, b, c, ... may
+// be a reference into str.
+// ----------------------------------------------------------------------
+
+LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b);
+LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
+ const AlphaNum& c);
+LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
+ const AlphaNum& c, const AlphaNum& d);
+LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
+ const AlphaNum& c, const AlphaNum& d,
+ const AlphaNum& e);
+LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
+ const AlphaNum& c, const AlphaNum& d,
+ const AlphaNum& e, const AlphaNum& f);
+LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
+ const AlphaNum& c, const AlphaNum& d,
+ const AlphaNum& e, const AlphaNum& f,
+ const AlphaNum& g);
+LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
+ const AlphaNum& c, const AlphaNum& d,
+ const AlphaNum& e, const AlphaNum& f,
+ const AlphaNum& g, const AlphaNum& h);
+LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b,
+ const AlphaNum& c, const AlphaNum& d,
+ const AlphaNum& e, const AlphaNum& f,
+ const AlphaNum& g, const AlphaNum& h,
+ const AlphaNum& i);
+
+inline string StrCat(const AlphaNum& a) { return string(a.data(), a.size()); }
+
+// ----------------------------------------------------------------------
+// StrAppend()
+// Same as above, but adds the output to the given string.
+// WARNING: For speed, StrAppend does not try to check each of its input
+// arguments to be sure that they are not a subset of the string being
+// appended to. That is, while this will work:
+//
+// string s = "foo";
+// s += s;
+//
+// This will not (necessarily) work:
+//
+// string s = "foo";
+// StrAppend(&s, s);
+//
+// Note: while StrCat supports appending up to 9 arguments, StrAppend
+// is currently limited to 4. That's rarely an issue except when
+// automatically transforming StrCat to StrAppend, and can easily be
+// worked around as consecutive calls to StrAppend are quite efficient.
+// ----------------------------------------------------------------------
+
+LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a);
+LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a,
+ const AlphaNum& b);
+LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a,
+ const AlphaNum& b, const AlphaNum& c);
+LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a,
+ const AlphaNum& b, const AlphaNum& c,
+ const AlphaNum& d);
// ----------------------------------------------------------------------
// Join()
@@ -559,7 +762,7 @@ void Join(Iterator start, Iterator end,
if (it != start) {
result->append(delim);
}
- result->append(internal::ToString(*it));
+ StrAppend(result, *it);
}
}
@@ -588,6 +791,83 @@ LIBPROTOBUF_EXPORT int GlobalReplaceSubstring(const string& substring,
const string& replacement,
string* s);
+// ----------------------------------------------------------------------
+// Base64Unescape()
+// Converts "src" which is encoded in Base64 to its binary equivalent and
+// writes it to "dest". If src contains invalid characters, dest is cleared
+// and the function returns false. Returns true on success.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT bool Base64Unescape(StringPiece src, string* dest);
+
+// ----------------------------------------------------------------------
+// WebSafeBase64Unescape()
+// This is a variation of Base64Unescape which uses '-' instead of '+', and
+// '_' instead of '/'. src is not null terminated, instead specify len. I
+// recommend that slen<szdest, but we honor szdest anyway.
+// RETURNS the length of dest, or -1 if src contains invalid chars.
+
+// The variation that stores into a string clears the string first, and
+// returns false (with dest empty) if src contains invalid chars; for
+// this version src and dest must be different strings.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT int WebSafeBase64Unescape(const char* src, int slen,
+ char* dest, int szdest);
+LIBPROTOBUF_EXPORT bool WebSafeBase64Unescape(StringPiece src, string* dest);
+
+// Return the length to use for the output buffer given to the base64 escape
+// routines. Make sure to use the same value for do_padding in both.
+// This function may return incorrect results if given input_len values that
+// are extremely high, which should happen rarely.
+LIBPROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len,
+ bool do_padding);
+// Use this version when calling Base64Escape without a do_padding arg.
+LIBPROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len);
+
+// ----------------------------------------------------------------------
+// Base64Escape()
+// WebSafeBase64Escape()
+// Encode "src" to "dest" using base64 encoding.
+// src is not null terminated, instead specify len.
+// 'dest' should have at least CalculateBase64EscapedLen() length.
+// RETURNS the length of dest.
+// The WebSafe variation use '-' instead of '+' and '_' instead of '/'
+// so that we can place the out in the URL or cookies without having
+// to escape them. It also has an extra parameter "do_padding",
+// which when set to false will prevent padding with "=".
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT int Base64Escape(const unsigned char* src, int slen,
+ char* dest, int szdest);
+LIBPROTOBUF_EXPORT int WebSafeBase64Escape(
+ const unsigned char* src, int slen, char* dest,
+ int szdest, bool do_padding);
+// Encode src into dest with padding.
+LIBPROTOBUF_EXPORT void Base64Escape(StringPiece src, string* dest);
+// Encode src into dest web-safely without padding.
+LIBPROTOBUF_EXPORT void WebSafeBase64Escape(StringPiece src, string* dest);
+// Encode src into dest web-safely with padding.
+LIBPROTOBUF_EXPORT void WebSafeBase64EscapeWithPadding(StringPiece src,
+ string* dest);
+
+LIBPROTOBUF_EXPORT void Base64Escape(const unsigned char* src, int szsrc,
+ string* dest, bool do_padding);
+LIBPROTOBUF_EXPORT void WebSafeBase64Escape(const unsigned char* src, int szsrc,
+ string* dest, bool do_padding);
+
+static const int UTFmax = 4;
+// ----------------------------------------------------------------------
+// EncodeAsUTF8Char()
+// Helper to append a Unicode code point to a string as UTF8, without bringing
+// in any external dependencies. The output buffer must be as least 4 bytes
+// large.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT int EncodeAsUTF8Char(uint32 code_point, char* output);
+
+// ----------------------------------------------------------------------
+// UTF8FirstLetterNumBytes()
+// Length of the first UTF-8 character.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT int UTF8FirstLetterNumBytes(const char* src, int len);
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/stubs/strutil_unittest.cc b/src/google/protobuf/stubs/strutil_unittest.cc
index 7f27dca0..5d62fc4a 100644
--- a/src/google/protobuf/stubs/strutil_unittest.cc
+++ b/src/google/protobuf/stubs/strutil_unittest.cc
@@ -32,9 +32,15 @@
#include <google/protobuf/stubs/strutil.h>
+#include <locale.h>
+
+#include <google/protobuf/stubs/stl_util.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
-#include <locale.h>
+
+#ifdef _WIN32
+#define snprintf _snprintf
+#endif
namespace google {
namespace protobuf {
@@ -68,6 +74,737 @@ TEST(StringUtilityTest, ImmuneToLocales) {
setlocale(LC_NUMERIC, old_locale.c_str());
}
+#define EXPECT_EQ_ARRAY(len, x, y, msg) \
+ for (int j = 0; j < len; ++j) { \
+ EXPECT_EQ(x[j], y[j]) << "" # x << " != " # y \
+ << " byte " << j << ": " << msg; \
+ }
+
+static struct {
+ int plain_length;
+ const char* plaintext;
+ const char* cyphertext;
+} base64_tests[] = {
+ // Empty string.
+ { 0, "", ""},
+
+ // Basic bit patterns;
+ // values obtained with "echo -n '...' | uuencode -m test"
+
+ { 1, "\000", "AA==" },
+ { 1, "\001", "AQ==" },
+ { 1, "\002", "Ag==" },
+ { 1, "\004", "BA==" },
+ { 1, "\010", "CA==" },
+ { 1, "\020", "EA==" },
+ { 1, "\040", "IA==" },
+ { 1, "\100", "QA==" },
+ { 1, "\200", "gA==" },
+
+ { 1, "\377", "/w==" },
+ { 1, "\376", "/g==" },
+ { 1, "\375", "/Q==" },
+ { 1, "\373", "+w==" },
+ { 1, "\367", "9w==" },
+ { 1, "\357", "7w==" },
+ { 1, "\337", "3w==" },
+ { 1, "\277", "vw==" },
+ { 1, "\177", "fw==" },
+ { 2, "\000\000", "AAA=" },
+ { 2, "\000\001", "AAE=" },
+ { 2, "\000\002", "AAI=" },
+ { 2, "\000\004", "AAQ=" },
+ { 2, "\000\010", "AAg=" },
+ { 2, "\000\020", "ABA=" },
+ { 2, "\000\040", "ACA=" },
+ { 2, "\000\100", "AEA=" },
+ { 2, "\000\200", "AIA=" },
+ { 2, "\001\000", "AQA=" },
+ { 2, "\002\000", "AgA=" },
+ { 2, "\004\000", "BAA=" },
+ { 2, "\010\000", "CAA=" },
+ { 2, "\020\000", "EAA=" },
+ { 2, "\040\000", "IAA=" },
+ { 2, "\100\000", "QAA=" },
+ { 2, "\200\000", "gAA=" },
+
+ { 2, "\377\377", "//8=" },
+ { 2, "\377\376", "//4=" },
+ { 2, "\377\375", "//0=" },
+ { 2, "\377\373", "//s=" },
+ { 2, "\377\367", "//c=" },
+ { 2, "\377\357", "/+8=" },
+ { 2, "\377\337", "/98=" },
+ { 2, "\377\277", "/78=" },
+ { 2, "\377\177", "/38=" },
+ { 2, "\376\377", "/v8=" },
+ { 2, "\375\377", "/f8=" },
+ { 2, "\373\377", "+/8=" },
+ { 2, "\367\377", "9/8=" },
+ { 2, "\357\377", "7/8=" },
+ { 2, "\337\377", "3/8=" },
+ { 2, "\277\377", "v/8=" },
+ { 2, "\177\377", "f/8=" },
+
+ { 3, "\000\000\000", "AAAA" },
+ { 3, "\000\000\001", "AAAB" },
+ { 3, "\000\000\002", "AAAC" },
+ { 3, "\000\000\004", "AAAE" },
+ { 3, "\000\000\010", "AAAI" },
+ { 3, "\000\000\020", "AAAQ" },
+ { 3, "\000\000\040", "AAAg" },
+ { 3, "\000\000\100", "AABA" },
+ { 3, "\000\000\200", "AACA" },
+ { 3, "\000\001\000", "AAEA" },
+ { 3, "\000\002\000", "AAIA" },
+ { 3, "\000\004\000", "AAQA" },
+ { 3, "\000\010\000", "AAgA" },
+ { 3, "\000\020\000", "ABAA" },
+ { 3, "\000\040\000", "ACAA" },
+ { 3, "\000\100\000", "AEAA" },
+ { 3, "\000\200\000", "AIAA" },
+ { 3, "\001\000\000", "AQAA" },
+ { 3, "\002\000\000", "AgAA" },
+ { 3, "\004\000\000", "BAAA" },
+ { 3, "\010\000\000", "CAAA" },
+ { 3, "\020\000\000", "EAAA" },
+ { 3, "\040\000\000", "IAAA" },
+ { 3, "\100\000\000", "QAAA" },
+ { 3, "\200\000\000", "gAAA" },
+
+ { 3, "\377\377\377", "////" },
+ { 3, "\377\377\376", "///+" },
+ { 3, "\377\377\375", "///9" },
+ { 3, "\377\377\373", "///7" },
+ { 3, "\377\377\367", "///3" },
+ { 3, "\377\377\357", "///v" },
+ { 3, "\377\377\337", "///f" },
+ { 3, "\377\377\277", "//+/" },
+ { 3, "\377\377\177", "//9/" },
+ { 3, "\377\376\377", "//7/" },
+ { 3, "\377\375\377", "//3/" },
+ { 3, "\377\373\377", "//v/" },
+ { 3, "\377\367\377", "//f/" },
+ { 3, "\377\357\377", "/+//" },
+ { 3, "\377\337\377", "/9//" },
+ { 3, "\377\277\377", "/7//" },
+ { 3, "\377\177\377", "/3//" },
+ { 3, "\376\377\377", "/v//" },
+ { 3, "\375\377\377", "/f//" },
+ { 3, "\373\377\377", "+///" },
+ { 3, "\367\377\377", "9///" },
+ { 3, "\357\377\377", "7///" },
+ { 3, "\337\377\377", "3///" },
+ { 3, "\277\377\377", "v///" },
+ { 3, "\177\377\377", "f///" },
+
+ // Random numbers: values obtained with
+ //
+ // #! /bin/bash
+ // dd bs=$1 count=1 if=/dev/random of=/tmp/bar.random
+ // od -N $1 -t o1 /tmp/bar.random
+ // uuencode -m test < /tmp/bar.random
+ //
+ // where $1 is the number of bytes (2, 3)
+
+ { 2, "\243\361", "o/E=" },
+ { 2, "\024\167", "FHc=" },
+ { 2, "\313\252", "y6o=" },
+ { 2, "\046\041", "JiE=" },
+ { 2, "\145\236", "ZZ4=" },
+ { 2, "\254\325", "rNU=" },
+ { 2, "\061\330", "Mdg=" },
+ { 2, "\245\032", "pRo=" },
+ { 2, "\006\000", "BgA=" },
+ { 2, "\375\131", "/Vk=" },
+ { 2, "\303\210", "w4g=" },
+ { 2, "\040\037", "IB8=" },
+ { 2, "\261\372", "sfo=" },
+ { 2, "\335\014", "3Qw=" },
+ { 2, "\233\217", "m48=" },
+ { 2, "\373\056", "+y4=" },
+ { 2, "\247\232", "p5o=" },
+ { 2, "\107\053", "Rys=" },
+ { 2, "\204\077", "hD8=" },
+ { 2, "\276\211", "vok=" },
+ { 2, "\313\110", "y0g=" },
+ { 2, "\363\376", "8/4=" },
+ { 2, "\251\234", "qZw=" },
+ { 2, "\103\262", "Q7I=" },
+ { 2, "\142\312", "Yso=" },
+ { 2, "\067\211", "N4k=" },
+ { 2, "\220\001", "kAE=" },
+ { 2, "\152\240", "aqA=" },
+ { 2, "\367\061", "9zE=" },
+ { 2, "\133\255", "W60=" },
+ { 2, "\176\035", "fh0=" },
+ { 2, "\032\231", "Gpk=" },
+
+ { 3, "\013\007\144", "Cwdk" },
+ { 3, "\030\112\106", "GEpG" },
+ { 3, "\047\325\046", "J9Um" },
+ { 3, "\310\160\022", "yHAS" },
+ { 3, "\131\100\237", "WUCf" },
+ { 3, "\064\342\134", "NOJc" },
+ { 3, "\010\177\004", "CH8E" },
+ { 3, "\345\147\205", "5WeF" },
+ { 3, "\300\343\360", "wOPw" },
+ { 3, "\061\240\201", "MaCB" },
+ { 3, "\225\333\044", "ldsk" },
+ { 3, "\215\137\352", "jV/q" },
+ { 3, "\371\147\160", "+Wdw" },
+ { 3, "\030\320\051", "GNAp" },
+ { 3, "\044\174\241", "JHyh" },
+ { 3, "\260\127\037", "sFcf" },
+ { 3, "\111\045\033", "SSUb" },
+ { 3, "\202\114\107", "gkxH" },
+ { 3, "\057\371\042", "L/ki" },
+ { 3, "\223\247\244", "k6ek" },
+ { 3, "\047\216\144", "J45k" },
+ { 3, "\203\070\327", "gzjX" },
+ { 3, "\247\140\072", "p2A6" },
+ { 3, "\124\115\116", "VE1O" },
+ { 3, "\157\162\050", "b3Io" },
+ { 3, "\357\223\004", "75ME" },
+ { 3, "\052\117\156", "Kk9u" },
+ { 3, "\347\154\000", "52wA" },
+ { 3, "\303\012\142", "wwpi" },
+ { 3, "\060\035\362", "MB3y" },
+ { 3, "\130\226\361", "WJbx" },
+ { 3, "\173\013\071", "ews5" },
+ { 3, "\336\004\027", "3gQX" },
+ { 3, "\357\366\234", "7/ac" },
+ { 3, "\353\304\111", "68RJ" },
+ { 3, "\024\264\131", "FLRZ" },
+ { 3, "\075\114\251", "PUyp" },
+ { 3, "\315\031\225", "zRmV" },
+ { 3, "\154\201\276", "bIG+" },
+ { 3, "\200\066\072", "gDY6" },
+ { 3, "\142\350\267", "Yui3" },
+ { 3, "\033\000\166", "GwB2" },
+ { 3, "\210\055\077", "iC0/" },
+ { 3, "\341\037\124", "4R9U" },
+ { 3, "\161\103\152", "cUNq" },
+ { 3, "\270\142\131", "uGJZ" },
+ { 3, "\337\076\074", "3z48" },
+ { 3, "\375\106\362", "/Uby" },
+ { 3, "\227\301\127", "l8FX" },
+ { 3, "\340\002\234", "4AKc" },
+ { 3, "\121\064\033", "UTQb" },
+ { 3, "\157\134\143", "b1xj" },
+ { 3, "\247\055\327", "py3X" },
+ { 3, "\340\142\005", "4GIF" },
+ { 3, "\060\260\143", "MLBj" },
+ { 3, "\075\203\170", "PYN4" },
+ { 3, "\143\160\016", "Y3AO" },
+ { 3, "\313\013\063", "ywsz" },
+ { 3, "\174\236\135", "fJ5d" },
+ { 3, "\103\047\026", "QycW" },
+ { 3, "\365\005\343", "9QXj" },
+ { 3, "\271\160\223", "uXCT" },
+ { 3, "\362\255\172", "8q16" },
+ { 3, "\113\012\015", "SwoN" },
+
+ // various lengths, generated by this python script:
+ //
+ // from string import lowercase as lc
+ // for i in range(27):
+ // print '{ %2d, "%s",%s "%s" },' % (i, lc[:i], ' ' * (26-i),
+ // lc[:i].encode('base64').strip())
+
+ { 0, "", "" },
+ { 1, "a", "YQ==" },
+ { 2, "ab", "YWI=" },
+ { 3, "abc", "YWJj" },
+ { 4, "abcd", "YWJjZA==" },
+ { 5, "abcde", "YWJjZGU=" },
+ { 6, "abcdef", "YWJjZGVm" },
+ { 7, "abcdefg", "YWJjZGVmZw==" },
+ { 8, "abcdefgh", "YWJjZGVmZ2g=" },
+ { 9, "abcdefghi", "YWJjZGVmZ2hp" },
+ { 10, "abcdefghij", "YWJjZGVmZ2hpag==" },
+ { 11, "abcdefghijk", "YWJjZGVmZ2hpams=" },
+ { 12, "abcdefghijkl", "YWJjZGVmZ2hpamts" },
+ { 13, "abcdefghijklm", "YWJjZGVmZ2hpamtsbQ==" },
+ { 14, "abcdefghijklmn", "YWJjZGVmZ2hpamtsbW4=" },
+ { 15, "abcdefghijklmno", "YWJjZGVmZ2hpamtsbW5v" },
+ { 16, "abcdefghijklmnop", "YWJjZGVmZ2hpamtsbW5vcA==" },
+ { 17, "abcdefghijklmnopq", "YWJjZGVmZ2hpamtsbW5vcHE=" },
+ { 18, "abcdefghijklmnopqr", "YWJjZGVmZ2hpamtsbW5vcHFy" },
+ { 19, "abcdefghijklmnopqrs", "YWJjZGVmZ2hpamtsbW5vcHFycw==" },
+ { 20, "abcdefghijklmnopqrst", "YWJjZGVmZ2hpamtsbW5vcHFyc3Q=" },
+ { 21, "abcdefghijklmnopqrstu", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1" },
+ { 22, "abcdefghijklmnopqrstuv", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dg==" },
+ { 23, "abcdefghijklmnopqrstuvw", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnc=" },
+ { 24, "abcdefghijklmnopqrstuvwx", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4" },
+ { 25, "abcdefghijklmnopqrstuvwxy", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eQ==" },
+ { 26, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=" },
+};
+
+static struct {
+ const char* plaintext;
+ const char* cyphertext;
+} base64_strings[] = {
+ // Some google quotes
+ // Cyphertext created with "uuencode (GNU sharutils) 4.6.3"
+ // (Note that we're testing the websafe encoding, though, so if
+ // you add messages, be sure to run "tr -- '+/' '-_'" on the output)
+ { "I was always good at math and science, and I never realized "
+ "that was unusual or somehow undesirable. So one of the things "
+ "I care a lot about is helping to remove that stigma, "
+ "to show girls that you can be feminine, you can like the things "
+ "that girls like, but you can also be really good at technology. "
+ "You can be really good at building things."
+ " - Marissa Meyer, Newsweek, 2010-12-22" "\n",
+
+ "SSB3YXMgYWx3YXlzIGdvb2QgYXQgbWF0aCBhbmQgc2NpZW5jZSwgYW5kIEkg"
+ "bmV2ZXIgcmVhbGl6ZWQgdGhhdCB3YXMgdW51c3VhbCBvciBzb21laG93IHVu"
+ "ZGVzaXJhYmxlLiBTbyBvbmUgb2YgdGhlIHRoaW5ncyBJIGNhcmUgYSBsb3Qg"
+ "YWJvdXQgaXMgaGVscGluZyB0byByZW1vdmUgdGhhdCBzdGlnbWEsIHRvIHNo"
+ "b3cgZ2lybHMgdGhhdCB5b3UgY2FuIGJlIGZlbWluaW5lLCB5b3UgY2FuIGxp"
+ "a2UgdGhlIHRoaW5ncyB0aGF0IGdpcmxzIGxpa2UsIGJ1dCB5b3UgY2FuIGFs"
+ "c28gYmUgcmVhbGx5IGdvb2QgYXQgdGVjaG5vbG9neS4gWW91IGNhbiBiZSBy"
+ "ZWFsbHkgZ29vZCBhdCBidWlsZGluZyB0aGluZ3MuIC0gTWFyaXNzYSBNZXll"
+ "ciwgTmV3c3dlZWssIDIwMTAtMTItMjIK" },
+
+ { "Typical first year for a new cluster: "
+ "~0.5 overheating "
+ "~1 PDU failure "
+ "~1 rack-move "
+ "~1 network rewiring "
+ "~20 rack failures "
+ "~5 racks go wonky "
+ "~8 network maintenances "
+ "~12 router reloads "
+ "~3 router failures "
+ "~dozens of minor 30-second blips for dns "
+ "~1000 individual machine failures "
+ "~thousands of hard drive failures "
+ "slow disks, bad memory, misconfigured machines, flaky machines, etc."
+ " - Jeff Dean, The Joys of Real Hardware" "\n",
+
+ "VHlwaWNhbCBmaXJzdCB5ZWFyIGZvciBhIG5ldyBjbHVzdGVyOiB-MC41IG92"
+ "ZXJoZWF0aW5nIH4xIFBEVSBmYWlsdXJlIH4xIHJhY2stbW92ZSB-MSBuZXR3"
+ "b3JrIHJld2lyaW5nIH4yMCByYWNrIGZhaWx1cmVzIH41IHJhY2tzIGdvIHdv"
+ "bmt5IH44IG5ldHdvcmsgbWFpbnRlbmFuY2VzIH4xMiByb3V0ZXIgcmVsb2Fk"
+ "cyB-MyByb3V0ZXIgZmFpbHVyZXMgfmRvemVucyBvZiBtaW5vciAzMC1zZWNv"
+ "bmQgYmxpcHMgZm9yIGRucyB-MTAwMCBpbmRpdmlkdWFsIG1hY2hpbmUgZmFp"
+ "bHVyZXMgfnRob3VzYW5kcyBvZiBoYXJkIGRyaXZlIGZhaWx1cmVzIHNsb3cg"
+ "ZGlza3MsIGJhZCBtZW1vcnksIG1pc2NvbmZpZ3VyZWQgbWFjaGluZXMsIGZs"
+ "YWt5IG1hY2hpbmVzLCBldGMuIC0gSmVmZiBEZWFuLCBUaGUgSm95cyBvZiBS"
+ "ZWFsIEhhcmR3YXJlCg" },
+
+ { "I'm the head of the webspam team at Google. "
+ "That means that if you type your name into Google and get porn back, "
+ "it's my fault. Unless you're a porn star, in which case porn is a "
+ "completely reasonable response."
+ " - Matt Cutts, Google Plus" "\n",
+
+ "SSdtIHRoZSBoZWFkIG9mIHRoZSB3ZWJzcGFtIHRlYW0gYXQgR29vZ2xlLiAg"
+ "VGhhdCBtZWFucyB0aGF0IGlmIHlvdSB0eXBlIHlvdXIgbmFtZSBpbnRvIEdv"
+ "b2dsZSBhbmQgZ2V0IHBvcm4gYmFjaywgaXQncyBteSBmYXVsdC4gVW5sZXNz"
+ "IHlvdSdyZSBhIHBvcm4gc3RhciwgaW4gd2hpY2ggY2FzZSBwb3JuIGlzIGEg"
+ "Y29tcGxldGVseSByZWFzb25hYmxlIHJlc3BvbnNlLiAtIE1hdHQgQ3V0dHMs"
+ "IEdvb2dsZSBQbHVzCg" },
+
+ { "It will still be a long time before machines approach human intelligence. "
+ "But luckily, machines don't actually have to be intelligent; "
+ "they just have to fake it. Access to a wealth of information, "
+ "combined with a rudimentary decision-making capacity, "
+ "can often be almost as useful. Of course, the results are better yet "
+ "when coupled with intelligence. A reference librarian with access to "
+ "a good search engine is a formidable tool."
+ " - Craig Silverstein, Siemens Pictures of the Future, Spring 2004" "\n",
+
+ "SXQgd2lsbCBzdGlsbCBiZSBhIGxvbmcgdGltZSBiZWZvcmUgbWFjaGluZXMg"
+ "YXBwcm9hY2ggaHVtYW4gaW50ZWxsaWdlbmNlLiBCdXQgbHVja2lseSwgbWFj"
+ "aGluZXMgZG9uJ3QgYWN0dWFsbHkgaGF2ZSB0byBiZSBpbnRlbGxpZ2VudDsg"
+ "dGhleSBqdXN0IGhhdmUgdG8gZmFrZSBpdC4gQWNjZXNzIHRvIGEgd2VhbHRo"
+ "IG9mIGluZm9ybWF0aW9uLCBjb21iaW5lZCB3aXRoIGEgcnVkaW1lbnRhcnkg"
+ "ZGVjaXNpb24tbWFraW5nIGNhcGFjaXR5LCBjYW4gb2Z0ZW4gYmUgYWxtb3N0"
+ "IGFzIHVzZWZ1bC4gT2YgY291cnNlLCB0aGUgcmVzdWx0cyBhcmUgYmV0dGVy"
+ "IHlldCB3aGVuIGNvdXBsZWQgd2l0aCBpbnRlbGxpZ2VuY2UuIEEgcmVmZXJl"
+ "bmNlIGxpYnJhcmlhbiB3aXRoIGFjY2VzcyB0byBhIGdvb2Qgc2VhcmNoIGVu"
+ "Z2luZSBpcyBhIGZvcm1pZGFibGUgdG9vbC4gLSBDcmFpZyBTaWx2ZXJzdGVp"
+ "biwgU2llbWVucyBQaWN0dXJlcyBvZiB0aGUgRnV0dXJlLCBTcHJpbmcgMjAw"
+ "NAo" },
+
+ // Degenerate edge case
+ { "",
+ "" },
+};
+
+TEST(Base64, EscapeAndUnescape) {
+ // Check the short strings; this tests the math (and boundaries)
+ for (int i = 0; i < sizeof(base64_tests) / sizeof(base64_tests[0]); ++i) {
+ char encode_buffer[100];
+ int encode_length;
+ char decode_buffer[100];
+ int decode_length;
+ int cypher_length;
+ string decode_str;
+
+ const unsigned char* unsigned_plaintext =
+ reinterpret_cast<const unsigned char*>(base64_tests[i].plaintext);
+
+ StringPiece plaintext(base64_tests[i].plaintext,
+ base64_tests[i].plain_length);
+
+ cypher_length = strlen(base64_tests[i].cyphertext);
+
+ // The basic escape function:
+ memset(encode_buffer, 0, sizeof(encode_buffer));
+ encode_length = Base64Escape(unsigned_plaintext,
+ base64_tests[i].plain_length,
+ encode_buffer,
+ sizeof(encode_buffer));
+ // Is it of the expected length?
+ EXPECT_EQ(encode_length, cypher_length);
+ // Would it have been okay to allocate only CalculateBase64EscapeLen()?
+ EXPECT_EQ(CalculateBase64EscapedLen(base64_tests[i].plain_length),
+ encode_length);
+
+ // Is it the expected encoded value?
+ ASSERT_STREQ(encode_buffer, base64_tests[i].cyphertext);
+
+ // If we encode it into a buffer of exactly the right length...
+ memset(encode_buffer, 0, sizeof(encode_buffer));
+ encode_length = Base64Escape(unsigned_plaintext,
+ base64_tests[i].plain_length,
+ encode_buffer,
+ cypher_length);
+ // Is it still of the expected length?
+ EXPECT_EQ(encode_length, cypher_length);
+
+ // And is the value still correct? (i.e., not losing the last byte)
+ EXPECT_STREQ(encode_buffer, base64_tests[i].cyphertext);
+
+ // If we decode it back:
+ decode_str.clear();
+ EXPECT_TRUE(Base64Unescape(
+ StringPiece(encode_buffer, cypher_length), &decode_str));
+
+ // Is it of the expected length?
+ EXPECT_EQ(base64_tests[i].plain_length, decode_str.length());
+
+ // Is it the expected decoded value?
+ EXPECT_EQ(plaintext, decode_str);
+
+ // Let's try with a pre-populated string.
+ string encoded("this junk should be ignored");
+ Base64Escape(string(base64_tests[i].plaintext,
+ base64_tests[i].plain_length),
+ &encoded);
+ EXPECT_EQ(encoded, string(encode_buffer, cypher_length));
+
+ string decoded("this junk should be ignored");
+ EXPECT_TRUE(Base64Unescape(
+ StringPiece(encode_buffer, cypher_length), &decoded));
+ EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
+ EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
+
+ // Our decoder treats the padding '=' characters at the end as
+ // optional (but if there are any, there must be the correct
+ // number of them.) If encode_buffer has any, run some additional
+ // tests that fiddle with them.
+ char* first_equals = strchr(encode_buffer, '=');
+ if (first_equals) {
+ // How many equals signs does the string start with?
+ int equals = (*(first_equals+1) == '=') ? 2 : 1;
+
+ // Try chopping off the equals sign(s) entirely. The decoder
+ // should still be okay with this.
+ string decoded2("this junk should also be ignored");
+ *first_equals = '\0';
+ EXPECT_TRUE(Base64Unescape(
+ StringPiece(encode_buffer, first_equals - encode_buffer), &decoded2));
+ EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
+ EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
+
+ // Now test chopping off the equals sign(s) and adding
+ // whitespace. Our decoder should still accept this.
+ decoded2.assign("this junk should be ignored");
+ *first_equals = ' ';
+ *(first_equals+1) = '\0';
+ EXPECT_TRUE(Base64Unescape(
+ StringPiece(encode_buffer, first_equals - encode_buffer + 1),
+ &decoded2));
+ EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
+ EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
+
+ // Now stick a bad character at the end of the string. The decoder
+ // should refuse this string.
+ decoded2.assign("this junk should be ignored");
+ *first_equals = '?';
+ *(first_equals+1) = '\0';
+ EXPECT_TRUE(
+ !Base64Unescape(
+ StringPiece(encode_buffer, first_equals - encode_buffer + 1),
+ &decoded2));
+
+ int len;
+
+ // Test whitespace mixed with the padding. (eg "AA = = ") The
+ // decoder should accept this.
+ if (equals == 2) {
+ snprintf(first_equals, 6, " = = ");
+ len = first_equals - encode_buffer + 5;
+ } else {
+ snprintf(first_equals, 6, " = ");
+ len = first_equals - encode_buffer + 3;
+ }
+ decoded2.assign("this junk should be ignored");
+ EXPECT_TRUE(
+ Base64Unescape(StringPiece(encode_buffer, len), &decoded2));
+ EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
+ EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
+
+ // Test whitespace mixed with the padding, but with the wrong
+ // number of equals signs (eg "AA = "). The decoder should
+ // refuse these strings.
+ if (equals == 1) {
+ snprintf(first_equals, 6, " = = ");
+ len = first_equals - encode_buffer + 5;
+ } else {
+ snprintf(first_equals, 6, " = ");
+ len = first_equals - encode_buffer + 3;
+ }
+ EXPECT_TRUE(
+ !Base64Unescape(StringPiece(encode_buffer, len), &decoded2));
+ }
+
+ // Cool! the basic Base64 encoder/decoder works.
+ // Let's try the alternate alphabet: tr -- '+/' '-_'
+
+ char websafe[100];
+ memset(websafe, 0, sizeof(websafe));
+ strncpy(websafe, base64_tests[i].cyphertext, cypher_length);
+ for (int c = 0; c < sizeof(websafe); ++c) {
+ if ('+' == websafe[c]) { websafe[c] = '-'; }
+ if ('/' == websafe[c]) { websafe[c] = '_'; }
+ }
+
+ // The websafe escape function:
+ memset(encode_buffer, 0, sizeof(encode_buffer));
+ encode_length = WebSafeBase64Escape(unsigned_plaintext,
+ base64_tests[i].plain_length,
+ encode_buffer,
+ sizeof(encode_buffer),
+ true);
+ // Is it of the expected length?
+ EXPECT_EQ(encode_length, cypher_length);
+ EXPECT_EQ(
+ CalculateBase64EscapedLen(base64_tests[i].plain_length, true),
+ encode_length);
+
+ // Is it the expected encoded value?
+ EXPECT_STREQ(encode_buffer, websafe);
+
+ // If we encode it into a buffer of exactly the right length...
+ memset(encode_buffer, 0, sizeof(encode_buffer));
+ encode_length = WebSafeBase64Escape(unsigned_plaintext,
+ base64_tests[i].plain_length,
+ encode_buffer,
+ cypher_length,
+ true);
+ // Is it still of the expected length?
+ EXPECT_EQ(encode_length, cypher_length);
+
+ // And is the value still correct? (i.e., not losing the last byte)
+ EXPECT_STREQ(encode_buffer, websafe);
+
+ // Let's try the string version of the encoder
+ encoded = "this junk should be ignored";
+ WebSafeBase64Escape(
+ unsigned_plaintext, base64_tests[i].plain_length,
+ &encoded, true);
+ EXPECT_EQ(encoded.size(), cypher_length);
+ EXPECT_STREQ(encoded.c_str(), websafe);
+
+ // If we decode it back:
+ memset(decode_buffer, 0, sizeof(decode_buffer));
+ decode_length = WebSafeBase64Unescape(encode_buffer,
+ cypher_length,
+ decode_buffer,
+ sizeof(decode_buffer));
+
+ // Is it of the expected length?
+ EXPECT_EQ(decode_length, base64_tests[i].plain_length);
+
+ // Is it the expected decoded value?
+ EXPECT_EQ(0,
+ memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
+
+ // If we decode it into a buffer of exactly the right length...
+ memset(decode_buffer, 0, sizeof(decode_buffer));
+ decode_length = WebSafeBase64Unescape(encode_buffer,
+ cypher_length,
+ decode_buffer,
+ decode_length);
+
+ // Is it still of the expected length?
+ EXPECT_EQ(decode_length, base64_tests[i].plain_length);
+
+ // And is it the expected decoded value?
+ EXPECT_EQ(0,
+ memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
+
+ // Try using '.' for the pad character.
+ for (int c = cypher_length - 1; c >= 0 && '=' == encode_buffer[c]; --c) {
+ encode_buffer[c] = '.';
+ }
+
+ // If we decode it back:
+ memset(decode_buffer, 0, sizeof(decode_buffer));
+ decode_length = WebSafeBase64Unescape(encode_buffer,
+ cypher_length,
+ decode_buffer,
+ sizeof(decode_buffer));
+
+ // Is it of the expected length?
+ EXPECT_EQ(decode_length, base64_tests[i].plain_length);
+
+ // Is it the expected decoded value?
+ EXPECT_EQ(0,
+ memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
+
+ // If we decode it into a buffer of exactly the right length...
+ memset(decode_buffer, 0, sizeof(decode_buffer));
+ decode_length = WebSafeBase64Unescape(encode_buffer,
+ cypher_length,
+ decode_buffer,
+ decode_length);
+
+ // Is it still of the expected length?
+ EXPECT_EQ(decode_length, base64_tests[i].plain_length);
+
+ // And is it the expected decoded value?
+ EXPECT_EQ(0,
+ memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
+
+ // Let's try the string version of the decoder
+ decoded = "this junk should be ignored";
+ EXPECT_TRUE(WebSafeBase64Unescape(
+ StringPiece(encode_buffer, cypher_length), &decoded));
+ EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
+ EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
+
+ // Okay! the websafe Base64 encoder/decoder works.
+ // Let's try the unpadded version
+
+ for (int c = 0; c < sizeof(websafe); ++c) {
+ if ('=' == websafe[c]) {
+ websafe[c] = '\0';
+ cypher_length = c;
+ break;
+ }
+ }
+
+ // The websafe escape function:
+ memset(encode_buffer, 0, sizeof(encode_buffer));
+ encode_length = WebSafeBase64Escape(unsigned_plaintext,
+ base64_tests[i].plain_length,
+ encode_buffer,
+ sizeof(encode_buffer),
+ false);
+ // Is it of the expected length?
+ EXPECT_EQ(encode_length, cypher_length);
+ EXPECT_EQ(
+ CalculateBase64EscapedLen(base64_tests[i].plain_length, false),
+ encode_length);
+
+ // Is it the expected encoded value?
+ EXPECT_STREQ(encode_buffer, websafe);
+
+ // If we encode it into a buffer of exactly the right length...
+ memset(encode_buffer, 0, sizeof(encode_buffer));
+ encode_length = WebSafeBase64Escape(unsigned_plaintext,
+ base64_tests[i].plain_length,
+ encode_buffer,
+ cypher_length,
+ false);
+ // Is it still of the expected length?
+ EXPECT_EQ(encode_length, cypher_length);
+
+ // And is the value still correct? (i.e., not losing the last byte)
+ EXPECT_STREQ(encode_buffer, websafe);
+
+ // Let's try the (other) string version of the encoder
+ string plain(base64_tests[i].plaintext, base64_tests[i].plain_length);
+ encoded = "this junk should be ignored";
+ WebSafeBase64Escape(plain, &encoded);
+ EXPECT_EQ(encoded.size(), cypher_length);
+ EXPECT_STREQ(encoded.c_str(), websafe);
+
+ // If we decode it back:
+ memset(decode_buffer, 0, sizeof(decode_buffer));
+ decode_length = WebSafeBase64Unescape(encode_buffer,
+ cypher_length,
+ decode_buffer,
+ sizeof(decode_buffer));
+
+ // Is it of the expected length?
+ EXPECT_EQ(decode_length, base64_tests[i].plain_length);
+
+ // Is it the expected decoded value?
+ EXPECT_EQ(0,
+ memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
+
+ // If we decode it into a buffer of exactly the right length...
+ memset(decode_buffer, 0, sizeof(decode_buffer));
+ decode_length = WebSafeBase64Unescape(encode_buffer,
+ cypher_length,
+ decode_buffer,
+ decode_length);
+
+ // Is it still of the expected length?
+ EXPECT_EQ(decode_length, base64_tests[i].plain_length);
+
+ // And is it the expected decoded value?
+ EXPECT_EQ(0,
+ memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
+
+
+ // Let's try the string version of the decoder
+ decoded = "this junk should be ignored";
+ EXPECT_TRUE(WebSafeBase64Unescape(
+ StringPiece(encode_buffer, cypher_length), &decoded));
+ EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
+ EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
+
+ // This value works. Try the next.
+ }
+
+ // Now try the long strings, this tests the streaming
+ for (int i = 0; i < sizeof(base64_strings) / sizeof(base64_strings[0]);
+ ++i) {
+ const unsigned char* unsigned_plaintext =
+ reinterpret_cast<const unsigned char*>(base64_strings[i].plaintext);
+ int plain_length = strlen(base64_strings[i].plaintext);
+ int cypher_length = strlen(base64_strings[i].cyphertext);
+ vector<char> buffer(cypher_length+1);
+ int encode_length = WebSafeBase64Escape(unsigned_plaintext,
+ plain_length,
+ &buffer[0],
+ buffer.size(),
+ false);
+ EXPECT_EQ(cypher_length, encode_length);
+ EXPECT_EQ(
+ CalculateBase64EscapedLen(plain_length, false), encode_length);
+ buffer[ encode_length ] = '\0';
+ EXPECT_STREQ(base64_strings[i].cyphertext, &buffer[0]);
+ }
+
+ // Verify the behavior when decoding bad data
+ {
+ const char* bad_data = "ab-/";
+ string buf;
+ EXPECT_FALSE(Base64Unescape(StringPiece(bad_data), &buf));
+ EXPECT_TRUE(!WebSafeBase64Unescape(bad_data, &buf));
+ EXPECT_TRUE(buf.empty());
+ }
+}
+
} // anonymous namespace
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/stubs/time.cc b/src/google/protobuf/stubs/time.cc
new file mode 100644
index 00000000..3319a244
--- /dev/null
+++ b/src/google/protobuf/stubs/time.cc
@@ -0,0 +1,366 @@
+#include <google/protobuf/stubs/time.h>
+
+#include <ctime>
+
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+namespace {
+static const int64 kSecondsPerMinute = 60;
+static const int64 kSecondsPerHour = 3600;
+static const int64 kSecondsPerDay = kSecondsPerHour * 24;
+static const int64 kSecondsPer400Years =
+ kSecondsPerDay * (400 * 365 + 400 / 4 - 3);
+// Seconds from 0001-01-01T00:00:00 to 1970-01-01T:00:00:00
+static const int64 kSecondsFromEraToEpoch = 62135596800LL;
+// The range of timestamp values we support.
+static const int64 kMinTime = -62135596800LL; // 0001-01-01T00:00:00
+static const int64 kMaxTime = 253402300799LL; // 9999-12-31T23:59:59
+
+static const int kNanosPerSecond = 1000000000;
+static const int kNanosPerMillisecond = 1000000;
+static const int kNanosPerMicrosecond = 1000;
+
+// Count the seconds from the given year (start at Jan 1, 00:00) to 100 years
+// after.
+int64 SecondsPer100Years(int year) {
+ if (year % 400 == 0 || year % 400 > 300) {
+ return kSecondsPerDay * (100 * 365 + 100 / 4);
+ } else {
+ return kSecondsPerDay * (100 * 365 + 100 / 4 - 1);
+ }
+}
+
+// Count the seconds from the given year (start at Jan 1, 00:00) to 4 years
+// after.
+int64 SecondsPer4Years(int year) {
+ if ((year % 100 == 0 || year % 100 > 96) &&
+ !(year % 400 == 0 || year % 400 > 396)) {
+ // No leap years.
+ return kSecondsPerDay * (4 * 365);
+ } else {
+ // One leap years.
+ return kSecondsPerDay * (4 * 365 + 1);
+ }
+}
+
+bool IsLeapYear(int year) {
+ return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
+}
+
+int64 SecondsPerYear(int year) {
+ return kSecondsPerDay * (IsLeapYear(year) ? 366 : 365);
+}
+
+static const int kDaysInMonth[13] = {
+ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+int64 SecondsPerMonth(int month, bool leap) {
+ if (month == 2 && leap) {
+ return kSecondsPerDay * (kDaysInMonth[month] + 1);
+ }
+ return kSecondsPerDay * kDaysInMonth[month];
+}
+
+static const int kDaysSinceJan[13] = {
+ 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
+};
+
+bool ValidateDateTime(const DateTime& time) {
+ if (time.year < 1 || time.year > 9999 ||
+ time.month < 1 || time.month > 12 ||
+ time.day < 1 || time.day > 31 ||
+ time.hour < 0 || time.hour > 23 ||
+ time.minute < 0 || time.minute > 59 ||
+ time.second < 0 || time.second > 59) {
+ return false;
+ }
+ if (time.month == 2 && IsLeapYear(time.year)) {
+ return time.month <= kDaysInMonth[time.month] + 1;
+ } else {
+ return time.month <= kDaysInMonth[time.month];
+ }
+}
+
+// Count the number of seconds elapsed from 0001-01-01T00:00:00 to the given
+// time.
+int64 SecondsSinceCommonEra(const DateTime& time) {
+ int64 result = 0;
+ // Years should be between 1 and 9999.
+ assert(time.year >= 1 && time.year <= 9999);
+ int year = 1;
+ if ((time.year - year) >= 400) {
+ int count_400years = (time.year - year) / 400;
+ result += kSecondsPer400Years * count_400years;
+ year += count_400years * 400;
+ }
+ while ((time.year - year) >= 100) {
+ result += SecondsPer100Years(year);
+ year += 100;
+ }
+ while ((time.year - year) >= 4) {
+ result += SecondsPer4Years(year);
+ year += 4;
+ }
+ while (time.year > year) {
+ result += SecondsPerYear(year);
+ ++year;
+ }
+ // Months should be between 1 and 12.
+ assert(time.month >= 1 && time.month <= 12);
+ int month = time.month;
+ result += kSecondsPerDay * kDaysSinceJan[month];
+ if (month > 2 && IsLeapYear(year)) {
+ result += kSecondsPerDay;
+ }
+ assert(time.day >= 1 &&
+ time.day <= (month == 2 && IsLeapYear(year)
+ ? kDaysInMonth[month] + 1
+ : kDaysInMonth[month]));
+ result += kSecondsPerDay * (time.day - 1);
+ result += kSecondsPerHour * time.hour +
+ kSecondsPerMinute * time.minute +
+ time.second;
+ return result;
+}
+
+// Format nanoseconds with either 3, 6, or 9 digits depending on the required
+// precision to represent the exact value.
+string FormatNanos(int32 nanos) {
+ if (nanos % kNanosPerMillisecond == 0) {
+ return StringPrintf("%03d", nanos / kNanosPerMillisecond);
+ } else if (nanos % kNanosPerMicrosecond == 0) {
+ return StringPrintf("%06d", nanos / kNanosPerMicrosecond);
+ } else {
+ return StringPrintf("%09d", nanos);
+ }
+}
+
+// Parses an integer from a null-terminated char sequence. The method
+// consumes at most "width" chars. Returns a pointer after the consumed
+// integer, or NULL if the data does not start with an integer or the
+// integer value does not fall in the range of [min_value, max_value].
+const char* ParseInt(const char* data, int width, int min_value,
+ int max_value, int* result) {
+ if (!ascii_isdigit(*data)) {
+ return NULL;
+ }
+ int value = 0;
+ for (int i = 0; i < width; ++i, ++data) {
+ if (ascii_isdigit(*data)) {
+ value = value * 10 + (*data - '0');
+ } else {
+ break;
+ }
+ }
+ if (value >= min_value && value <= max_value) {
+ *result = value;
+ return data;
+ } else {
+ return NULL;
+ }
+}
+
+// Consumes the fractional parts of a second into nanos. For example,
+// "010" will be parsed to 10000000 nanos.
+const char* ParseNanos(const char* data, int32* nanos) {
+ if (!ascii_isdigit(*data)) {
+ return NULL;
+ }
+ int value = 0;
+ int len = 0;
+ // Consume as many digits as there are but only take the first 9 into
+ // account.
+ while (ascii_isdigit(*data)) {
+ if (len < 9) {
+ value = value * 10 + *data - '0';
+ }
+ ++len;
+ ++data;
+ }
+ while (len < 9) {
+ value = value * 10;
+ ++len;
+ }
+ *nanos = value;
+ return data;
+}
+
+const char* ParseTimezoneOffset(const char* data, int64* offset) {
+ // Accept format "HH:MM". E.g., "08:00"
+ int hour;
+ if ((data = ParseInt(data, 2, 0, 23, &hour)) == NULL) {
+ return NULL;
+ }
+ if (*data++ != ':') {
+ return NULL;
+ }
+ int minute;
+ if ((data = ParseInt(data, 2, 0, 59, &minute)) == NULL) {
+ return NULL;
+ }
+ *offset = (hour * 60 + minute) * 60;
+ return data;
+}
+} // namespace
+
+bool SecondsToDateTime(int64 seconds, DateTime* time) {
+ if (seconds < kMinTime || seconds > kMaxTime) {
+ return false;
+ }
+ // It's easier to calcuate the DateTime starting from 0001-01-01T00:00:00
+ seconds = seconds + kSecondsFromEraToEpoch;
+ int year = 1;
+ if (seconds >= kSecondsPer400Years) {
+ int count_400years = seconds / kSecondsPer400Years;
+ year += 400 * count_400years;
+ seconds %= kSecondsPer400Years;
+ }
+ while (seconds >= SecondsPer100Years(year)) {
+ seconds -= SecondsPer100Years(year);
+ year += 100;
+ }
+ while (seconds >= SecondsPer4Years(year)) {
+ seconds -= SecondsPer4Years(year);
+ year += 4;
+ }
+ while (seconds >= SecondsPerYear(year)) {
+ seconds -= SecondsPerYear(year);
+ year += 1;
+ }
+ bool leap = IsLeapYear(year);
+ int month = 1;
+ while (seconds >= SecondsPerMonth(month, leap)) {
+ seconds -= SecondsPerMonth(month, leap);
+ ++month;
+ }
+ int day = 1 + seconds / kSecondsPerDay;
+ seconds %= kSecondsPerDay;
+ int hour = seconds / kSecondsPerHour;
+ seconds %= kSecondsPerHour;
+ int minute = seconds / kSecondsPerMinute;
+ seconds %= kSecondsPerMinute;
+ time->year = year;
+ time->month = month;
+ time->day = day;
+ time->hour = hour;
+ time->minute = minute;
+ time->second = static_cast<int>(seconds);
+ return true;
+}
+
+bool DateTimeToSeconds(const DateTime& time, int64* seconds) {
+ if (!ValidateDateTime(time)) {
+ return false;
+ }
+ *seconds = SecondsSinceCommonEra(time) - kSecondsFromEraToEpoch;
+ return true;
+}
+
+void GetCurrentTime(int64* seconds, int32* nanos) {
+ // TODO(xiaofeng): Improve the accuracy of this implementation (or just
+ // remove this method from protobuf).
+ *seconds = time(NULL);
+ *nanos = 0;
+}
+
+string FormatTime(int64 seconds, int32 nanos) {
+ DateTime time;
+ if (nanos < 0 || nanos > 999999999 || !SecondsToDateTime(seconds, &time)) {
+ return "InvalidTime";
+ }
+ string result = StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d",
+ time.year, time.month, time.day,
+ time.hour, time.minute, time.second);
+ if (nanos != 0) {
+ result += "." + FormatNanos(nanos);
+ }
+ return result + "Z";
+}
+
+bool ParseTime(const string& value, int64* seconds, int32* nanos) {
+ DateTime time;
+ const char* data = value.c_str();
+ // We only accept:
+ // Z-normalized: 2015-05-20T13:29:35.120Z
+ // With UTC offset: 2015-05-20T13:29:35.120-08:00
+
+ // Parse year
+ if ((data = ParseInt(data, 4, 1, 9999, &time.year)) == NULL) {
+ return false;
+ }
+ // Expect '-'
+ if (*data++ != '-') return false;
+ // Parse month
+ if ((data = ParseInt(data, 2, 1, 12, &time.month)) == NULL) {
+ return false;
+ }
+ // Expect '-'
+ if (*data++ != '-') return false;
+ // Parse day
+ if ((data = ParseInt(data, 2, 1, 31, &time.day)) == NULL) {
+ return false;
+ }
+ // Expect 'T'
+ if (*data++ != 'T') return false;
+ // Parse hour
+ if ((data = ParseInt(data, 2, 0, 23, &time.hour)) == NULL) {
+ return false;
+ }
+ // Expect ':'
+ if (*data++ != ':') return false;
+ // Parse minute
+ if ((data = ParseInt(data, 2, 0, 59, &time.minute)) == NULL) {
+ return false;
+ }
+ // Expect ':'
+ if (*data++ != ':') return false;
+ // Parse second
+ if ((data = ParseInt(data, 2, 0, 59, &time.second)) == NULL) {
+ return false;
+ }
+ if (!DateTimeToSeconds(time, seconds)) {
+ return false;
+ }
+ // Parse nanoseconds.
+ if (*data == '.') {
+ ++data;
+ // Parse nanoseconds.
+ if ((data = ParseNanos(data, nanos)) == NULL) {
+ return false;
+ }
+ } else {
+ *nanos = 0;
+ }
+ // Parse UTC offsets.
+ if (*data == 'Z') {
+ ++data;
+ } else if (*data == '+') {
+ ++data;
+ int64 offset;
+ if ((data = ParseTimezoneOffset(data, &offset)) == NULL) {
+ return false;
+ }
+ *seconds -= offset;
+ } else if (*data == '-') {
+ ++data;
+ int64 offset;
+ if ((data = ParseTimezoneOffset(data, &offset)) == NULL) {
+ return false;
+ }
+ *seconds += offset;
+ } else {
+ return false;
+ }
+ // Done with parsing.
+ return *data == 0;
+}
+
+} // namespace internal
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/time.h b/src/google/protobuf/stubs/time.h
new file mode 100644
index 00000000..20a6b56d
--- /dev/null
+++ b/src/google/protobuf/stubs/time.h
@@ -0,0 +1,75 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifndef GOOGLE_PROTOBUF_STUBS_TIME_H_
+#define GOOGLE_PROTOBUF_STUBS_TIME_H_
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+struct DateTime {
+ int year;
+ int month;
+ int day;
+ int hour;
+ int minute;
+ int second;
+};
+
+// Converts a timestamp (seconds elapsed since 1970-01-01T00:00:00, could be
+// negative to represent time before 1970-01-01) to DateTime. Returns false
+// if the timestamp is not in the range between 0001-01-01T00:00:00 and
+// 9999-12-31T23:59:59.
+bool LIBPROTOBUF_EXPORT SecondsToDateTime(int64 seconds, DateTime* time);
+// Converts DateTime to a timestamp (seconds since 1970-01-01T00:00:00).
+// Returns false if the DateTime is not valid or is not in the valid range.
+bool LIBPROTOBUF_EXPORT DateTimeToSeconds(const DateTime& time, int64* seconds);
+
+void LIBPROTOBUF_EXPORT GetCurrentTime(int64* seconds, int32* nanos);
+
+// Formats a time string in RFC3339 fromat.
+//
+// For example, "2015-05-20T13:29:35.120Z". For nanos, 0, 3, 6 or 9 fractional
+// digits will be used depending on how many are required to represent the exact
+// value.
+//
+// Note that "nanos" must in the range of [0, 999999999].
+string LIBPROTOBUF_EXPORT FormatTime(int64 seconds, int32 nanos);
+// Parses a time string. This method accepts RFC3339 date/time string with UTC
+// offset. For example, "2015-05-20T13:29:35.120-08:00".
+bool LIBPROTOBUF_EXPORT ParseTime(const string& vaule, int64* seconds, int32* nanos);
+
+} // namespace internal
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_TIME_H_
diff --git a/src/google/protobuf/stubs/time_test.cc b/src/google/protobuf/stubs/time_test.cc
new file mode 100644
index 00000000..59e9d1c7
--- /dev/null
+++ b/src/google/protobuf/stubs/time_test.cc
@@ -0,0 +1,208 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include <google/protobuf/stubs/time.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+namespace {
+static const int64 kSecondsPerDay = 3600 * 24;
+
+// For DateTime, tests will mostly focuse on the date part because that's
+// the tricky one.
+int64 CreateTimestamp(int year, int month, int day) {
+ DateTime time;
+ time.year = year;
+ time.month = month;
+ time.day = day;
+ time.hour = time.minute = time.second = 0;
+ int64 result;
+ GOOGLE_CHECK(DateTimeToSeconds(time, &result));
+ // Check that a roundtrip produces the same result.
+ GOOGLE_CHECK(SecondsToDateTime(result, &time));
+ GOOGLE_CHECK(time.year == year);
+ GOOGLE_CHECK(time.month == month);
+ GOOGLE_CHECK(time.day == day);
+ return result;
+}
+
+TEST(DateTimeTest, SimpleTime) {
+ DateTime time;
+ ASSERT_TRUE(SecondsToDateTime(1, &time));
+ EXPECT_EQ(1970, time.year);
+ EXPECT_EQ(1, time.month);
+ EXPECT_EQ(1, time.day);
+ EXPECT_EQ(0, time.hour);
+ EXPECT_EQ(0, time.minute);
+ EXPECT_EQ(1, time.second);
+ int64 seconds;
+ ASSERT_TRUE(DateTimeToSeconds(time, &seconds));
+ EXPECT_EQ(1, seconds);
+
+ ASSERT_TRUE(SecondsToDateTime(-1, &time));
+ EXPECT_EQ(1969, time.year);
+ EXPECT_EQ(12, time.month);
+ EXPECT_EQ(31, time.day);
+ EXPECT_EQ(23, time.hour);
+ EXPECT_EQ(59, time.minute);
+ EXPECT_EQ(59, time.second);
+ ASSERT_TRUE(DateTimeToSeconds(time, &seconds));
+ EXPECT_EQ(-1, seconds);
+
+ DateTime start, end;
+ start.year = 1;
+ start.month = 1;
+ start.day = 1;
+ start.hour = 0;
+ start.minute = 0;
+ start.second = 0;
+ end.year = 9999;
+ end.month = 12;
+ end.day = 31;
+ end.hour = 23;
+ end.minute = 59;
+ end.second = 59;
+ int64 start_time, end_time;
+ ASSERT_TRUE(DateTimeToSeconds(start, &start_time));
+ ASSERT_TRUE(DateTimeToSeconds(end, &end_time));
+ EXPECT_EQ(315537897599LL, end_time - start_time);
+ ASSERT_TRUE(SecondsToDateTime(start_time, &time));
+ ASSERT_TRUE(DateTimeToSeconds(time, &seconds));
+ EXPECT_EQ(start_time, seconds);
+ ASSERT_TRUE(SecondsToDateTime(end_time, &time));
+ ASSERT_TRUE(DateTimeToSeconds(time, &seconds));
+ EXPECT_EQ(end_time, seconds);
+}
+
+TEST(DateTimeTest, DayInMonths) {
+ // Check that month boundaries are handled correctly.
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2015, 1, 1) - CreateTimestamp(2014, 12, 31));
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2015, 2, 1) - CreateTimestamp(2015, 1, 31));
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2015, 3, 1) - CreateTimestamp(2015, 2, 28));
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2015, 4, 1) - CreateTimestamp(2015, 3, 31));
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2015, 5, 1) - CreateTimestamp(2015, 4, 30));
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2015, 6, 1) - CreateTimestamp(2015, 5, 31));
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2015, 7, 1) - CreateTimestamp(2015, 6, 30));
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2015, 8, 1) - CreateTimestamp(2015, 7, 31));
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2015, 9, 1) - CreateTimestamp(2015, 8, 31));
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2015, 10, 1) - CreateTimestamp(2015, 9, 30));
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2015, 11, 1) - CreateTimestamp(2015, 10, 31));
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2015, 12, 1) - CreateTimestamp(2015, 11, 30));
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2016, 1, 1) - CreateTimestamp(2015, 12, 31));
+}
+
+TEST(DateTimeTest, LeapYear) {
+ // Non-leap year.
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2015, 3, 1) - CreateTimestamp(2015, 2, 28));
+ // Leap year.
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2016, 3, 1) - CreateTimestamp(2016, 2, 29));
+ // Non-leap year.
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2100, 3, 1) - CreateTimestamp(2100, 2, 28));
+ // Leap year.
+ EXPECT_EQ(kSecondsPerDay,
+ CreateTimestamp(2400, 3, 1) - CreateTimestamp(2400, 2, 29));
+}
+
+TEST(DateTimeTest, StringFormat) {
+ DateTime start, end;
+ start.year = 1;
+ start.month = 1;
+ start.day = 1;
+ start.hour = 0;
+ start.minute = 0;
+ start.second = 0;
+ end.year = 9999;
+ end.month = 12;
+ end.day = 31;
+ end.hour = 23;
+ end.minute = 59;
+ end.second = 59;
+ int64 start_time, end_time;
+ ASSERT_TRUE(DateTimeToSeconds(start, &start_time));
+ ASSERT_TRUE(DateTimeToSeconds(end, &end_time));
+
+ EXPECT_EQ("0001-01-01T00:00:00Z", FormatTime(start_time, 0));
+ EXPECT_EQ("9999-12-31T23:59:59Z", FormatTime(end_time, 0));
+
+ // Make sure the nanoseconds part is formated correctly.
+ EXPECT_EQ("1970-01-01T00:00:00.010Z", FormatTime(0, 10000000));
+ EXPECT_EQ("1970-01-01T00:00:00.000010Z", FormatTime(0, 10000));
+ EXPECT_EQ("1970-01-01T00:00:00.000000010Z", FormatTime(0, 10));
+}
+
+TEST(DateTimeTest, ParseString) {
+ int64 seconds;
+ int32 nanos;
+ ASSERT_TRUE(ParseTime("0001-01-01T00:00:00Z", &seconds, &nanos));
+ EXPECT_EQ("0001-01-01T00:00:00Z", FormatTime(seconds, nanos));
+ ASSERT_TRUE(ParseTime("9999-12-31T23:59:59.999999999Z", &seconds, &nanos));
+ EXPECT_EQ("9999-12-31T23:59:59.999999999Z", FormatTime(seconds, nanos));
+
+ // Test time zone offsets.
+ ASSERT_TRUE(ParseTime("1970-01-01T00:00:00-08:00", &seconds, &nanos));
+ EXPECT_EQ("1970-01-01T08:00:00Z", FormatTime(seconds, nanos));
+ ASSERT_TRUE(ParseTime("1970-01-01T00:00:00+08:00", &seconds, &nanos));
+ EXPECT_EQ("1969-12-31T16:00:00Z", FormatTime(seconds, nanos));
+
+ // Test nanoseconds.
+ ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.01Z", &seconds, &nanos));
+ EXPECT_EQ("1970-01-01T00:00:00.010Z", FormatTime(seconds, nanos));
+ ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.00001-08:00", &seconds, &nanos));
+ EXPECT_EQ("1970-01-01T08:00:00.000010Z", FormatTime(seconds, nanos));
+ ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.00000001+08:00", &seconds, &nanos));
+ EXPECT_EQ("1969-12-31T16:00:00.000000010Z", FormatTime(seconds, nanos));
+ // Fractional parts less than 1 nanosecond will be ignored.
+ ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.0123456789Z", &seconds, &nanos));
+ EXPECT_EQ("1970-01-01T00:00:00.012345678Z", FormatTime(seconds, nanos));
+}
+
+} // namespace
+} // namespace internal
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/type_traits.h b/src/google/protobuf/stubs/type_traits.h
index b58cae3f..0d8127e5 100644
--- a/src/google/protobuf/stubs/type_traits.h
+++ b/src/google/protobuf/stubs/type_traits.h
@@ -59,9 +59,9 @@
#ifndef GOOGLE_PROTOBUF_TYPE_TRAITS_H_
#define GOOGLE_PROTOBUF_TYPE_TRAITS_H_
+#include <cstddef> // for NULL
#include <utility> // For pair
-#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/template_util.h> // For true_type and false_type
namespace google {
@@ -73,6 +73,10 @@ struct is_base_of {
typedef char (&yes)[1];
typedef char (&no)[2];
+ // BEGIN GOOGLE LOCAL MODIFICATION -- check is a #define on Mac.
+ #undef check
+ // END GOOGLE LOCAL MODIFICATION
+
static yes check(const B*);
static no check(const void*);
diff --git a/src/google/protobuf/testdata/golden_message_proto3 b/src/google/protobuf/testdata/golden_message_proto3
new file mode 100644
index 00000000..bd646a0d
--- /dev/null
+++ b/src/google/protobuf/testdata/golden_message_proto3
Binary files differ
diff --git a/src/google/protobuf/testdata/map_test_data.txt b/src/google/protobuf/testdata/map_test_data.txt
new file mode 100644
index 00000000..bc272321
--- /dev/null
+++ b/src/google/protobuf/testdata/map_test_data.txt
@@ -0,0 +1,140 @@
+map_int32_int32 {
+ key: 0
+ value: 0
+}
+map_int32_int32 {
+ key: 1
+ value: 1
+}
+map_int64_int64 {
+ key: 0
+ value: 0
+}
+map_int64_int64 {
+ key: 1
+ value: 1
+}
+map_uint32_uint32 {
+ key: 0
+ value: 0
+}
+map_uint32_uint32 {
+ key: 1
+ value: 1
+}
+map_uint64_uint64 {
+ key: 0
+ value: 0
+}
+map_uint64_uint64 {
+ key: 1
+ value: 1
+}
+map_sint32_sint32 {
+ key: 0
+ value: 0
+}
+map_sint32_sint32 {
+ key: 1
+ value: 1
+}
+map_sint64_sint64 {
+ key: 0
+ value: 0
+}
+map_sint64_sint64 {
+ key: 1
+ value: 1
+}
+map_fixed32_fixed32 {
+ key: 0
+ value: 0
+}
+map_fixed32_fixed32 {
+ key: 1
+ value: 1
+}
+map_fixed64_fixed64 {
+ key: 0
+ value: 0
+}
+map_fixed64_fixed64 {
+ key: 1
+ value: 1
+}
+map_sfixed32_sfixed32 {
+ key: 0
+ value: 0
+}
+map_sfixed32_sfixed32 {
+ key: 1
+ value: 1
+}
+map_sfixed64_sfixed64 {
+ key: 0
+ value: 0
+}
+map_sfixed64_sfixed64 {
+ key: 1
+ value: 1
+}
+map_int32_float {
+ key: 0
+ value: 0
+}
+map_int32_float {
+ key: 1
+ value: 1
+}
+map_int32_double {
+ key: 0
+ value: 0
+}
+map_int32_double {
+ key: 1
+ value: 1
+}
+map_bool_bool {
+ key: false
+ value: false
+}
+map_bool_bool {
+ key: true
+ value: true
+}
+map_string_string {
+ key: "0"
+ value: "0"
+}
+map_string_string {
+ key: "1"
+ value: "1"
+}
+map_int32_bytes {
+ key: 0
+ value: "0"
+}
+map_int32_bytes {
+ key: 1
+ value: "1"
+}
+map_int32_enum {
+ key: 0
+ value: MAP_ENUM_BAR
+}
+map_int32_enum {
+ key: 1
+ value: MAP_ENUM_BAZ
+}
+map_int32_foreign_message {
+ key: 0
+ value {
+ c: 0
+ }
+}
+map_int32_foreign_message {
+ key: 1
+ value {
+ c: 1
+ }
+}
diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc
index 5344ec15..3d07b127 100644
--- a/src/google/protobuf/testing/file.cc
+++ b/src/google/protobuf/testing/file.cc
@@ -192,5 +192,9 @@ void File::DeleteRecursively(const string& name,
#endif
}
+bool File::ChangeWorkingDirectory(const string& new_working_directory) {
+ return chdir(new_working_directory.c_str()) == 0;
+}
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/testing/file.h b/src/google/protobuf/testing/file.h
index d2aeabf2..2f63f80e 100644
--- a/src/google/protobuf/testing/file.h
+++ b/src/google/protobuf/testing/file.h
@@ -77,6 +77,9 @@ class File {
static void DeleteRecursively(const string& name,
void* dummy1, void* dummy2);
+ // Change working directory to given directory.
+ static bool ChangeWorkingDirectory(const string& new_working_directory);
+
static bool GetContents(
const string& name, string* output, bool /*is_default*/) {
return ReadFileToString(name, output);
diff --git a/src/google/protobuf/testing/googletest.cc b/src/google/protobuf/testing/googletest.cc
index d72fa5c0..b8bd790b 100644
--- a/src/google/protobuf/testing/googletest.cc
+++ b/src/google/protobuf/testing/googletest.cc
@@ -65,7 +65,15 @@ namespace protobuf {
#endif
string TestSourceDir() {
-#ifdef _MSC_VER
+#ifndef GOOGLE_THIRD_PARTY_PROTOBUF
+#ifndef _MSC_VER
+ // automake sets the "srcdir" environment variable.
+ char* result = getenv("srcdir");
+ if (result != NULL) {
+ return result;
+ }
+#endif // _MSC_VER
+
// Look for the "src" directory.
string prefix = ".";
@@ -79,15 +87,8 @@ string TestSourceDir() {
}
return prefix + "/src";
#else
- // automake sets the "srcdir" environment variable.
- char* result = getenv("srcdir");
- if (result == NULL) {
- // Otherwise, the test must be run from the source directory.
- return ".";
- } else {
- return result;
- }
-#endif
+ return "third_party/protobuf/src";
+#endif // GOOGLE_THIRD_PARTY_PROTOBUF
}
namespace {
@@ -104,6 +105,10 @@ string GetTemporaryDirectoryName() {
if (HasPrefixString(result, "\\")) {
result.erase(0, 1);
}
+ // The Win32 API accepts forward slashes as a path delimiter even though
+ // backslashes are standard. Let's avoid confusion and use only forward
+ // slashes.
+ result = StringReplace(result, "\\", "/", true);
#endif // _WIN32
return result;
}
diff --git a/src/google/protobuf/testing/zcgunzip.cc b/src/google/protobuf/testing/zcgunzip.cc
index daf74ff1..76f8cfe1 100644
--- a/src/google/protobuf/testing/zcgunzip.cc
+++ b/src/google/protobuf/testing/zcgunzip.cc
@@ -38,13 +38,20 @@
// Reads gzip stream on standard input and writes decompressed data to standard
// output.
-#include "config.h"
-
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
+#ifdef _WIN32
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+#endif
+
#include <google/protobuf/io/gzip_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
diff --git a/src/google/protobuf/testing/zcgzip.cc b/src/google/protobuf/testing/zcgzip.cc
index a4101999..992ddc6e 100644
--- a/src/google/protobuf/testing/zcgzip.cc
+++ b/src/google/protobuf/testing/zcgzip.cc
@@ -38,12 +38,19 @@
// Reads data on standard input and writes compressed gzip stream to standard
// output.
-#include "config.h"
-
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
+#ifdef _WIN32
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+#endif
+
#include <google/protobuf/io/gzip_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index 8e867c09..4d8c1f91 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -43,6 +43,8 @@
#include <google/protobuf/text_format.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/repeated_field.h>
#include <google/protobuf/wire_format_lite.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream.h>
@@ -50,6 +52,7 @@
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/any.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/map_util.h>
@@ -70,6 +73,18 @@ inline bool IsOctNumber(const string& str) {
(str[1] >= '0' && str[1] < '8'));
}
+inline bool GetAnyFieldDescriptors(const Message& message,
+ const FieldDescriptor** type_url_field,
+ const FieldDescriptor** value_field) {
+ const Descriptor* descriptor = message.GetDescriptor();
+ *type_url_field = descriptor->FindFieldByNumber(1);
+ *value_field = descriptor->FindFieldByNumber(2);
+ return (*type_url_field != NULL &&
+ (*type_url_field)->type() == FieldDescriptor::TYPE_STRING &&
+ *value_field != NULL &&
+ (*value_field)->type() == FieldDescriptor::TYPE_BYTES);
+}
+
} // namespace
string Message::DebugString() const {
@@ -330,7 +345,17 @@ class TextFormat::Parser::ParserImpl {
// Confirm that we have a valid ending delimiter.
DO(Consume(delimiter));
+ return true;
+ }
+ // Consume either "<" or "{".
+ bool ConsumeMessageDelimiter(string* delimiter) {
+ if (TryConsume("<")) {
+ *delimiter = ">";
+ } else {
+ DO(Consume("{"));
+ *delimiter = "}";
+ }
return true;
}
@@ -347,15 +372,28 @@ class TextFormat::Parser::ParserImpl {
int start_line = tokenizer_.current().line;
int start_column = tokenizer_.current().column;
+ const FieldDescriptor* any_type_url_field;
+ const FieldDescriptor* any_value_field;
+ if (internal::GetAnyFieldDescriptors(*message, &any_type_url_field,
+ &any_value_field) &&
+ TryConsume("[")) {
+ string full_type_name;
+ DO(ConsumeAnyTypeUrl(&full_type_name));
+ DO(Consume("]"));
+ string serialized_value;
+ DO(ConsumeAnyValue(full_type_name,
+ message->GetDescriptor()->file()->pool(),
+ &serialized_value));
+ reflection->SetString(
+ message, any_type_url_field,
+ string(internal::kTypeGoogleApisComPrefix) + full_type_name);
+ reflection->SetString(message, any_value_field, serialized_value);
+ return true;
+ // Fall through.
+ }
if (TryConsume("[")) {
// Extension.
- DO(ConsumeIdentifier(&field_name));
- while (TryConsume(".")) {
- string part;
- DO(ConsumeIdentifier(&part));
- field_name += ".";
- field_name += part;
- }
+ DO(ConsumeFullTypeName(&field_name));
DO(Consume("]"));
field = (finder_ != NULL
@@ -512,13 +550,7 @@ class TextFormat::Parser::ParserImpl {
string field_name;
if (TryConsume("[")) {
// Extension name.
- DO(ConsumeIdentifier(&field_name));
- while (TryConsume(".")) {
- string part;
- DO(ConsumeIdentifier(&part));
- field_name += ".";
- field_name += part;
- }
+ DO(ConsumeFullTypeName(&field_name));
DO(Consume("]"));
} else {
DO(ConsumeIdentifier(&field_name));
@@ -553,13 +585,7 @@ class TextFormat::Parser::ParserImpl {
}
string delimiter;
- if (TryConsume("<")) {
- delimiter = ">";
- } else {
- DO(Consume("{"));
- delimiter = "}";
- }
-
+ DO(ConsumeMessageDelimiter(&delimiter));
if (field->is_repeated()) {
DO(ConsumeMessage(reflection->AddMessage(message, field), delimiter));
} else {
@@ -576,12 +602,7 @@ class TextFormat::Parser::ParserImpl {
// the ending delimiter.
bool SkipFieldMessage() {
string delimiter;
- if (TryConsume("<")) {
- delimiter = ">";
- } else {
- DO(Consume("{"));
- delimiter = "}";
- }
+ DO(ConsumeMessageDelimiter(&delimiter));
while (!LookingAt(">") && !LookingAt("}")) {
DO(SkipField());
}
@@ -808,6 +829,18 @@ class TextFormat::Parser::ParserImpl {
return false;
}
+ // Consume a string of form "<id1>.<id2>....<idN>".
+ bool ConsumeFullTypeName(string* name) {
+ DO(ConsumeIdentifier(name));
+ while (TryConsume(".")) {
+ string part;
+ DO(ConsumeIdentifier(&part));
+ *name += ".";
+ *name += part;
+ }
+ return true;
+ }
+
// Consumes a string and saves its value in the text parameter.
// Returns false if the token is not of type STRING.
bool ConsumeString(string* text) {
@@ -947,6 +980,54 @@ class TextFormat::Parser::ParserImpl {
return true;
}
+ // Consumes Any::type_url value, of form "type.googleapis.com/full.type.Name"
+ bool ConsumeAnyTypeUrl(string* full_type_name) {
+ // TODO(saito) Extend Consume() to consume multiple tokens at once, so that
+ // this code can be written as just DO(Consume(kGoogleApisTypePrefix)).
+ string url1, url2, url3;
+ DO(ConsumeIdentifier(&url1)); // type
+ DO(Consume("."));
+ DO(ConsumeIdentifier(&url2)); // googleapis
+ DO(Consume("."));
+ DO(ConsumeIdentifier(&url3)); // com
+ DO(Consume("/"));
+ DO(ConsumeFullTypeName(full_type_name));
+
+ const string prefix = url1 + "." + url2 + "." + url3 + "/";
+ if (prefix != internal::kTypeGoogleApisComPrefix) {
+ ReportError("TextFormat::Parser for Any supports only "
+ "type.googleapi.com, but found \"" + prefix + "\"");
+ return false;
+ }
+ return true;
+ }
+
+ // A helper function for reconstructing Any::value. Consumes a text of
+ // full_type_name, then serializes it into serialized_value. "pool" is used to
+ // look up and create a temporary object with full_type_name.
+ bool ConsumeAnyValue(const string& full_type_name, const DescriptorPool* pool,
+ string* serialized_value) {
+ const Descriptor* value_descriptor =
+ pool->FindMessageTypeByName(full_type_name);
+ if (value_descriptor == NULL) {
+ ReportError("Could not find type \"" + full_type_name +
+ "\" stored in google.protobuf.Any.");
+ return false;
+ }
+ DynamicMessageFactory factory;
+ const Message* value_prototype = factory.GetPrototype(value_descriptor);
+ if (value_prototype == NULL) {
+ return false;
+ }
+ google::protobuf::scoped_ptr<Message> value(value_prototype->New());
+ string sub_delimiter;
+ DO(ConsumeMessageDelimiter(&sub_delimiter));
+ DO(ConsumeMessage(value.get(), sub_delimiter));
+
+ value->AppendToString(serialized_value);
+ return true;
+ }
+
// Consumes a token and confirms that it matches that specified in the
// value parameter. Returns false if the token found does not match that
// which was specified.
@@ -1338,7 +1419,8 @@ TextFormat::Printer::Printer()
use_field_number_(false),
use_short_repeated_primitives_(false),
hide_unknown_fields_(false),
- print_message_fields_in_index_order_(false) {
+ print_message_fields_in_index_order_(false),
+ expand_any_(false) {
SetUseUtf8StringEscaping(false);
}
@@ -1360,9 +1442,8 @@ void TextFormat::Printer::SetDefaultFieldValuePrinter(
bool TextFormat::Printer::RegisterFieldValuePrinter(
const FieldDescriptor* field,
const FieldValuePrinter* printer) {
- return field != NULL
- && printer != NULL
- && custom_printers_.insert(make_pair(field, printer)).second;
+ return field != NULL && printer != NULL &&
+ custom_printers_.insert(std::make_pair(field, printer)).second;
}
bool TextFormat::Printer::PrintToString(const Message& message,
@@ -1414,15 +1495,67 @@ struct FieldIndexSorter {
return left->index() < right->index();
}
};
+
} // namespace
+bool TextFormat::Printer::PrintAny(const Message& message,
+ TextGenerator& generator) const {
+ const FieldDescriptor* type_url_field;
+ const FieldDescriptor* value_field;
+ if (!internal::GetAnyFieldDescriptors(message, &type_url_field,
+ &value_field)) {
+ return false;
+ }
+
+ const Reflection* reflection = message.GetReflection();
+
+ // Extract the full type name from the type_url field.
+ const string& type_url = reflection->GetString(message, type_url_field);
+ string full_type_name;
+ if (!internal::ParseAnyTypeUrl(type_url, &full_type_name)) {
+ return false;
+ }
+
+ // Print the "value" in text.
+ const google::protobuf::Descriptor* value_descriptor =
+ message.GetDescriptor()->file()->pool()->FindMessageTypeByName(
+ full_type_name);
+ if (value_descriptor == NULL) {
+ GOOGLE_LOG(WARNING) << "Proto type " << type_url << " not found";
+ return false;
+ }
+ DynamicMessageFactory factory;
+ google::protobuf::scoped_ptr<google::protobuf::Message> value_message(
+ factory.GetPrototype(value_descriptor)->New());
+ string serialized_value = reflection->GetString(message, value_field);
+ if (!value_message->ParseFromString(serialized_value)) {
+ GOOGLE_LOG(WARNING) << type_url << ": failed to parse contents";
+ return false;
+ }
+ generator.Print(StrCat("[", type_url, "]"));
+ const FieldValuePrinter* printer = FindWithDefault(
+ custom_printers_, value_field, default_field_value_printer_.get());
+ generator.Print(
+ printer->PrintMessageStart(message, -1, 0, single_line_mode_));
+ generator.Indent();
+ Print(*value_message, generator);
+ generator.Outdent();
+ generator.Print(printer->PrintMessageEnd(message, -1, 0, single_line_mode_));
+ return true;
+}
+
void TextFormat::Printer::Print(const Message& message,
TextGenerator& generator) const {
+ const Descriptor* descriptor = message.GetDescriptor();
const Reflection* reflection = message.GetReflection();
+ if (descriptor->full_name() == internal::kAnyFullTypeName && expand_any_ &&
+ PrintAny(message, generator)) {
+ return;
+ }
vector<const FieldDescriptor*> fields;
reflection->ListFields(message, &fields);
if (print_message_fields_in_index_order_) {
- sort(fields.begin(), fields.end(), FieldIndexSorter());
+ std::sort(fields.begin(), fields.end(), FieldIndexSorter());
}
for (int i = 0; i < fields.size(); i++) {
PrintField(message, reflection, fields[i], generator);
@@ -1447,6 +1580,54 @@ void TextFormat::Printer::PrintFieldValueToString(
PrintFieldValue(message, message.GetReflection(), field, index, generator);
}
+class MapEntryMessageComparator {
+ public:
+ explicit MapEntryMessageComparator(const Descriptor* descriptor)
+ : field_(descriptor->field(0)) {}
+
+ bool operator()(const Message* a, const Message* b) {
+ const Reflection* reflection = a->GetReflection();
+ switch (field_->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_BOOL: {
+ bool first = reflection->GetBool(*a, field_);
+ bool second = reflection->GetBool(*b, field_);
+ return first < second;
+ }
+ case FieldDescriptor::CPPTYPE_INT32: {
+ int32 first = reflection->GetInt32(*a, field_);
+ int32 second = reflection->GetInt32(*b, field_);
+ return first < second;
+ }
+ case FieldDescriptor::CPPTYPE_INT64: {
+ int64 first = reflection->GetInt64(*a, field_);
+ int64 second = reflection->GetInt64(*b, field_);
+ return first < second;
+ }
+ case FieldDescriptor::CPPTYPE_UINT32: {
+ uint32 first = reflection->GetUInt32(*a, field_);
+ uint32 second = reflection->GetUInt32(*b, field_);
+ return first < second;
+ }
+ case FieldDescriptor::CPPTYPE_UINT64: {
+ uint64 first = reflection->GetUInt64(*a, field_);
+ uint64 second = reflection->GetUInt64(*b, field_);
+ return first < second;
+ }
+ case FieldDescriptor::CPPTYPE_STRING: {
+ string first = reflection->GetString(*a, field_);
+ string second = reflection->GetString(*b, field_);
+ return first < second;
+ }
+ default:
+ GOOGLE_LOG(DFATAL) << "Invalid key for map field.";
+ return true;
+ }
+ }
+
+ private:
+ const FieldDescriptor* field_;
+};
+
void TextFormat::Printer::PrintField(const Message& message,
const Reflection* reflection,
const FieldDescriptor* field,
@@ -1467,6 +1648,21 @@ void TextFormat::Printer::PrintField(const Message& message,
count = 1;
}
+ std::vector<const Message*> sorted_map_field;
+ if (field->is_map()) {
+ const RepeatedPtrField<Message>& map_field =
+ reflection->GetRepeatedPtrField<Message>(message, field);
+ for (RepeatedPtrField<Message>::const_pointer_iterator it =
+ map_field.pointer_begin();
+ it != map_field.pointer_end(); ++it) {
+ sorted_map_field.push_back(*it);
+ }
+
+ MapEntryMessageComparator comparator(field->message_type());
+ std::stable_sort(sorted_map_field.begin(), sorted_map_field.end(),
+ comparator);
+ }
+
for (int j = 0; j < count; ++j) {
const int field_index = field->is_repeated() ? j : -1;
@@ -1476,8 +1672,10 @@ void TextFormat::Printer::PrintField(const Message& message,
const FieldValuePrinter* printer = FindWithDefault(
custom_printers_, field, default_field_value_printer_.get());
const Message& sub_message =
- field->is_repeated()
- ? reflection->GetRepeatedMessage(message, field, j)
+ field->is_repeated()
+ ? (field->is_map()
+ ? *sorted_map_field[j]
+ : reflection->GetRepeatedMessage(message, field, j))
: reflection->GetMessage(message, field);
generator.Print(
printer->PrintMessageStart(
@@ -1681,8 +1879,8 @@ void TextFormat::Printer::PrintUnknownFields(
case UnknownField::TYPE_FIXED32: {
generator.Print(field_number);
generator.Print(": 0x");
- char buffer[kFastToBufferSize];
- generator.Print(FastHex32ToBuffer(field.fixed32(), buffer));
+ generator.Print(
+ StrCat(strings::Hex(field.fixed32(), strings::ZERO_PAD_8)));
if (single_line_mode_) {
generator.Print(" ");
} else {
@@ -1693,8 +1891,8 @@ void TextFormat::Printer::PrintUnknownFields(
case UnknownField::TYPE_FIXED64: {
generator.Print(field_number);
generator.Print(": 0x");
- char buffer[kFastToBufferSize];
- generator.Print(FastHex64ToBuffer(field.fixed64(), buffer));
+ generator.Print(
+ StrCat(strings::Hex(field.fixed64(), strings::ZERO_PAD_16)));
if (single_line_mode_) {
generator.Print(" ");
} else {
diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
index 44d68cab..6717aecd 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -208,6 +208,17 @@ class LIBPROTOBUF_EXPORT TextFormat {
print_message_fields_in_index_order;
}
+ // If expand==true, expand google.protobuf.Any payloads. The output
+ // will be of form
+ // [type_url] { <value_printed_in_text> }
+ //
+ // If expand==false, print Any using the default printer. The output will
+ // look like
+ // type_url: "<type_url>" value: "serialized_content"
+ void SetExpandAny(bool expand) {
+ expand_any_ = expand;
+ }
+
// Register a custom field-specific FieldValuePrinter for fields
// with a particular FieldDescriptor.
// Returns "true" if the registration succeeded, or "false", if there is
@@ -259,6 +270,8 @@ class LIBPROTOBUF_EXPORT TextFormat {
void PrintUnknownFields(const UnknownFieldSet& unknown_fields,
TextGenerator& generator) const;
+ bool PrintAny(const Message& message, TextGenerator& generator) const;
+
int initial_indent_level_;
bool single_line_mode_;
@@ -271,6 +284,8 @@ class LIBPROTOBUF_EXPORT TextFormat {
bool print_message_fields_in_index_order_;
+ bool expand_any_;
+
google::protobuf::scoped_ptr<const FieldValuePrinter> default_field_value_printer_;
typedef map<const FieldDescriptor*,
const FieldValuePrinter*> CustomPrinterMap;
@@ -278,8 +293,20 @@ class LIBPROTOBUF_EXPORT TextFormat {
};
// Parses a text-format protocol message from the given input stream to
- // the given message object. This function parses the format written
- // by Print().
+ // the given message object. This function parses the human-readable format
+ // written by Print(). Returns true on success. The message is cleared first,
+ // even if the function fails -- See Merge() to avoid this behavior.
+ //
+ // Example input: "user {\n id: 123 extra { gender: MALE language: 'en' }\n}"
+ //
+ // One use for this function is parsing handwritten strings in test code.
+ // Another use is to parse the output from google::protobuf::Message::DebugString()
+ // (or ShortDebugString()), because these functions output using
+ // google::protobuf::TextFormat::Print().
+ //
+ // If you would like to read a protocol buffer serialized in the
+ // (non-human-readable) binary wire format, see
+ // google::protobuf::MessageLite::ParseFromString().
static bool Parse(io::ZeroCopyInputStream* input, Message* output);
// Like Parse(), but reads directly from a string.
static bool ParseFromString(const string& input, Message* output);
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index 477fdcbd..76ce9875 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -32,23 +32,25 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <google/protobuf/text_format.h>
+
#include <math.h>
#include <stdlib.h>
#include <limits>
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/io/tokenizer.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_mset.pb.h>
-#include <google/protobuf/test_util.h>
-
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_mset.pb.h>
+#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>
+
namespace google {
namespace protobuf {
@@ -56,11 +58,6 @@ namespace protobuf {
// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
namespace text_format_unittest {
-inline bool IsNaN(double value) {
- // NaN is never equal to anything, even itself.
- return value != value;
-}
-
// A basic string with different escapable characters for testing.
const string kEscapeTestString =
"\"A string with ' characters \n and \r newlines and \t tabs and \001 "
@@ -451,7 +448,7 @@ TEST_F(TextFormatTest, ErrorCasesRegisteringFieldValuePrinterShouldFail) {
class CustomMessageFieldValuePrinter : public TextFormat::FieldValuePrinter {
public:
virtual string PrintInt32(int32 v) const {
- return StrCat(FieldValuePrinter::PrintInt32(v), " # x", ToHex(v));
+ return StrCat(FieldValuePrinter::PrintInt32(v), " # x", strings::Hex(v));
}
virtual string PrintMessageStart(const Message& message,
@@ -897,8 +894,8 @@ TEST_F(TextFormatTest, ParseExotic) {
EXPECT_EQ(message.repeated_double(8), numeric_limits<double>::infinity());
EXPECT_EQ(message.repeated_double(9), -numeric_limits<double>::infinity());
EXPECT_EQ(message.repeated_double(10), -numeric_limits<double>::infinity());
- EXPECT_TRUE(IsNaN(message.repeated_double(11)));
- EXPECT_TRUE(IsNaN(message.repeated_double(12)));
+ EXPECT_TRUE(MathLimits<double>::IsNaN(message.repeated_double(11)));
+ EXPECT_TRUE(MathLimits<double>::IsNaN(message.repeated_double(12)));
// Note: Since these string literals have \0's in them, we must explicitly
// pass their sizes to string's constructor.
diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc
new file mode 100644
index 00000000..2ee0ec29
--- /dev/null
+++ b/src/google/protobuf/timestamp.pb.cc
@@ -0,0 +1,407 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/timestamp.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "google/protobuf/timestamp.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* Timestamp_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ Timestamp_reflection_ = NULL;
+
+} // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2ftimestamp_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto();
+ const ::google::protobuf::FileDescriptor* file =
+ ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+ "google/protobuf/timestamp.proto");
+ GOOGLE_CHECK(file != NULL);
+ Timestamp_descriptor_ = file->message_type(0);
+ static const int Timestamp_offsets_[2] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Timestamp, seconds_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Timestamp, nanos_),
+ };
+ Timestamp_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ Timestamp_descriptor_,
+ Timestamp::default_instance_,
+ Timestamp_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(Timestamp),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Timestamp, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Timestamp, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+ ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+ &protobuf_AssignDesc_google_2fprotobuf_2ftimestamp_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ Timestamp_descriptor_, &Timestamp::default_instance());
+}
+
+} // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2ftimestamp_2eproto() {
+ delete Timestamp::default_instance_;
+ delete Timestamp_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto() {
+ static bool already_here = false;
+ if (already_here) return;
+ already_here = true;
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ ::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(\005BQ\n\023com.google.protobufB\016"
+ "TimestampProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Proto"
+ "buf.WellKnownTypesb\006proto3", 186);
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+ "google/protobuf/timestamp.proto", &protobuf_RegisterTypes);
+ Timestamp::default_instance_ = new Timestamp();
+ Timestamp::default_instance_->InitAsDefaultInstance();
+ ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2ftimestamp_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2ftimestamp_2eproto {
+ StaticDescriptorInitializer_google_2fprotobuf_2ftimestamp_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto();
+ }
+} static_descriptor_initializer_google_2fprotobuf_2ftimestamp_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+ GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+} // namespace
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int Timestamp::kSecondsFieldNumber;
+const int Timestamp::kNanosFieldNumber;
+#endif // !_MSC_VER
+
+Timestamp::Timestamp()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.Timestamp)
+}
+
+void Timestamp::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+Timestamp::Timestamp(const Timestamp& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.Timestamp)
+}
+
+void Timestamp::SharedCtor() {
+ _is_default_instance_ = false;
+ _cached_size_ = 0;
+ seconds_ = GOOGLE_LONGLONG(0);
+ nanos_ = 0;
+}
+
+Timestamp::~Timestamp() {
+ // @@protoc_insertion_point(destructor:google.protobuf.Timestamp)
+ SharedDtor();
+}
+
+void Timestamp::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void Timestamp::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Timestamp::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Timestamp_descriptor_;
+}
+
+const Timestamp& Timestamp::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto();
+ return *default_instance_;
+}
+
+Timestamp* Timestamp::default_instance_ = NULL;
+
+Timestamp* Timestamp::New(::google::protobuf::Arena* arena) const {
+ Timestamp* n = new Timestamp;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void Timestamp::Clear() {
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<Timestamp*>(16)->f)
+
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+ ZR_(seconds_, nanos_);
+
+#undef ZR_HELPER_
+#undef ZR_
+
+}
+
+bool Timestamp::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.Timestamp)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional int64 seconds = 1;
+ case 1: {
+ if (tag == 8) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
+ input, &seconds_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(16)) goto parse_nanos;
+ break;
+ }
+
+ // optional int32 nanos = 2;
+ case 2: {
+ if (tag == 16) {
+ parse_nanos:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &nanos_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.Timestamp)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.Timestamp)
+ return false;
+#undef DO_
+}
+
+void Timestamp::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.Timestamp)
+ // optional int64 seconds = 1;
+ if (this->seconds() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt64(1, this->seconds(), output);
+ }
+
+ // optional int32 nanos = 2;
+ if (this->nanos() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->nanos(), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.Timestamp)
+}
+
+::google::protobuf::uint8* Timestamp::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Timestamp)
+ // optional int64 seconds = 1;
+ if (this->seconds() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(1, this->seconds(), target);
+ }
+
+ // optional int32 nanos = 2;
+ if (this->nanos() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->nanos(), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Timestamp)
+ return target;
+}
+
+int Timestamp::ByteSize() const {
+ int total_size = 0;
+
+ // optional int64 seconds = 1;
+ if (this->seconds() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int64Size(
+ this->seconds());
+ }
+
+ // optional int32 nanos = 2;
+ if (this->nanos() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->nanos());
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void Timestamp::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const Timestamp* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Timestamp>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void Timestamp::MergeFrom(const Timestamp& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from.seconds() != 0) {
+ set_seconds(from.seconds());
+ }
+ if (from.nanos() != 0) {
+ set_nanos(from.nanos());
+ }
+}
+
+void Timestamp::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void Timestamp::CopyFrom(const Timestamp& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Timestamp::IsInitialized() const {
+
+ return true;
+}
+
+void Timestamp::Swap(Timestamp* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void Timestamp::InternalSwap(Timestamp* other) {
+ std::swap(seconds_, other->seconds_);
+ std::swap(nanos_, other->nanos_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Timestamp::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = Timestamp_descriptor_;
+ metadata.reflection = Timestamp_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Timestamp
+
+// optional int64 seconds = 1;
+void Timestamp::clear_seconds() {
+ seconds_ = GOOGLE_LONGLONG(0);
+}
+ ::google::protobuf::int64 Timestamp::seconds() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.seconds)
+ return seconds_;
+}
+ void Timestamp::set_seconds(::google::protobuf::int64 value) {
+
+ seconds_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.seconds)
+}
+
+// optional int32 nanos = 2;
+void Timestamp::clear_nanos() {
+ nanos_ = 0;
+}
+ ::google::protobuf::int32 Timestamp::nanos() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.nanos)
+ return nanos_;
+}
+ void Timestamp::set_nanos(::google::protobuf::int32 value) {
+
+ nanos_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.nanos)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/timestamp.pb.h b/src/google/protobuf/timestamp.pb.h
new file mode 100644
index 00000000..85fc1242
--- /dev/null
+++ b/src/google/protobuf/timestamp.pb.h
@@ -0,0 +1,172 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/timestamp.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2ftimestamp_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2ftimestamp_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2ftimestamp_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2ftimestamp_2eproto();
+
+class Timestamp;
+
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT Timestamp : public ::google::protobuf::Message {
+ public:
+ Timestamp();
+ virtual ~Timestamp();
+
+ Timestamp(const Timestamp& from);
+
+ inline Timestamp& operator=(const Timestamp& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const Timestamp& default_instance();
+
+ void Swap(Timestamp* other);
+
+ // implements Message ----------------------------------------------
+
+ inline Timestamp* New() const { return New(NULL); }
+
+ Timestamp* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const Timestamp& from);
+ void MergeFrom(const Timestamp& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(Timestamp* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional int64 seconds = 1;
+ void clear_seconds();
+ static const int kSecondsFieldNumber = 1;
+ ::google::protobuf::int64 seconds() const;
+ void set_seconds(::google::protobuf::int64 value);
+
+ // optional int32 nanos = 2;
+ void clear_nanos();
+ static const int kNanosFieldNumber = 2;
+ ::google::protobuf::int32 nanos() const;
+ void set_nanos(::google::protobuf::int32 value);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.Timestamp)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::int64 seconds_;
+ ::google::protobuf::int32 nanos_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2ftimestamp_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2ftimestamp_2eproto();
+
+ void InitAsDefaultInstance();
+ static Timestamp* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// Timestamp
+
+// optional int64 seconds = 1;
+inline void Timestamp::clear_seconds() {
+ seconds_ = GOOGLE_LONGLONG(0);
+}
+inline ::google::protobuf::int64 Timestamp::seconds() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.seconds)
+ return seconds_;
+}
+inline void Timestamp::set_seconds(::google::protobuf::int64 value) {
+
+ seconds_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.seconds)
+}
+
+// optional int32 nanos = 2;
+inline void Timestamp::clear_nanos() {
+ nanos_ = 0;
+}
+inline ::google::protobuf::int32 Timestamp::nanos() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.nanos)
+ return nanos_;
+}
+inline void Timestamp::set_nanos(::google::protobuf::int32 value) {
+
+ nanos_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.nanos)
+}
+
+#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif // PROTOBUF_google_2fprotobuf_2ftimestamp_2eproto__INCLUDED
diff --git a/src/google/protobuf/timestamp.proto b/src/google/protobuf/timestamp.proto
new file mode 100644
index 00000000..11f258da
--- /dev/null
+++ b/src/google/protobuf/timestamp.proto
@@ -0,0 +1,106 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+syntax = "proto3";
+
+package google.protobuf;
+
+option java_generate_equals_and_hash = true;
+option java_multiple_files = true;
+option java_outer_classname = "TimestampProto";
+option java_package = "com.google.protobuf";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option objc_class_prefix = "GPB";
+
+
+// A Timestamp represents a point in time independent of any time zone
+// or calendar, represented as seconds and fractions of seconds at
+// nanosecond resolution in UTC Epoch time. It is encoded using the
+// Proleptic Gregorian Calendar which extends the Gregorian calendar
+// backwards to year one. It is encoded assuming all minutes are 60
+// seconds long, i.e. leap seconds are "smeared" so that no leap second
+// table is needed for interpretation. Range is from
+// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
+// By restricting to that range, we ensure that we can convert to
+// and from RFC 3339 date strings.
+// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
+//
+// Example 1: Compute Timestamp from POSIX `time()`.
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(time(NULL));
+// timestamp.set_nanos(0);
+//
+// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
+//
+// struct timeval tv;
+// gettimeofday(&tv, NULL);
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(tv.tv_sec);
+// timestamp.set_nanos(tv.tv_usec * 1000);
+//
+// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+//
+// FILETIME ft;
+// GetSystemTimeAsFileTime(&ft);
+// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+//
+// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+// Timestamp timestamp;
+// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+//
+// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
+//
+// long millis = System.currentTimeMillis();
+//
+// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+// .setNanos((int) ((millis % 1000) * 1000000)).build();
+//
+// Example 5: Compute Timestamp from Python `datetime.datetime`.
+//
+// now = datetime.datetime.utcnow()
+// seconds = int(time.mktime(now.timetuple()))
+// nanos = now.microsecond * 1000
+// timestamp = Timestamp(seconds=seconds, nanos=nanos)
+//
+message Timestamp {
+ // Represents seconds of UTC time since Unix epoch
+ // 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to
+ // 9999-12-31T23:59:59Z inclusive.
+ int64 seconds = 1;
+
+ // Non-negative fractions of a second at nanosecond resolution. Negative
+ // second values with fractions must still have non-negative nanos values
+ // that count forward in time. Must be from 0 to 999,999,999
+ // inclusive.
+ int32 nanos = 2;
+}
diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc
new file mode 100644
index 00000000..029a72c6
--- /dev/null
+++ b/src/google/protobuf/type.pb.cc
@@ -0,0 +1,2899 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/type.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "google/protobuf/type.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* Type_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ Type_reflection_ = NULL;
+const ::google::protobuf::Descriptor* Field_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ Field_reflection_ = NULL;
+const ::google::protobuf::EnumDescriptor* Field_Kind_descriptor_ = NULL;
+const ::google::protobuf::EnumDescriptor* Field_Cardinality_descriptor_ = NULL;
+const ::google::protobuf::Descriptor* Enum_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ Enum_reflection_ = NULL;
+const ::google::protobuf::Descriptor* EnumValue_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ EnumValue_reflection_ = NULL;
+const ::google::protobuf::Descriptor* Option_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ Option_reflection_ = NULL;
+
+} // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+ const ::google::protobuf::FileDescriptor* file =
+ ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+ "google/protobuf/type.proto");
+ GOOGLE_CHECK(file != NULL);
+ Type_descriptor_ = file->message_type(0);
+ static const int Type_offsets_[5] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, name_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, fields_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, oneofs_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, options_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, source_context_),
+ };
+ Type_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ Type_descriptor_,
+ Type::default_instance_,
+ Type_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(Type),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, _is_default_instance_));
+ Field_descriptor_ = file->message_type(1);
+ static const int Field_offsets_[8] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, kind_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, cardinality_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, number_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, name_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, type_url_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, oneof_index_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, packed_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, options_),
+ };
+ Field_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ Field_descriptor_,
+ Field::default_instance_,
+ Field_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(Field),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, _is_default_instance_));
+ Field_Kind_descriptor_ = Field_descriptor_->enum_type(0);
+ Field_Cardinality_descriptor_ = Field_descriptor_->enum_type(1);
+ Enum_descriptor_ = file->message_type(2);
+ static const int Enum_offsets_[4] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, name_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, enumvalue_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, options_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, source_context_),
+ };
+ Enum_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ Enum_descriptor_,
+ Enum::default_instance_,
+ Enum_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(Enum),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, _is_default_instance_));
+ EnumValue_descriptor_ = file->message_type(3);
+ static const int EnumValue_offsets_[3] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValue, name_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValue, number_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValue, options_),
+ };
+ EnumValue_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ EnumValue_descriptor_,
+ EnumValue::default_instance_,
+ EnumValue_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(EnumValue),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValue, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValue, _is_default_instance_));
+ Option_descriptor_ = file->message_type(4);
+ static const int Option_offsets_[2] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Option, name_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Option, value_),
+ };
+ Option_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ Option_descriptor_,
+ Option::default_instance_,
+ Option_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(Option),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Option, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Option, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+ ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+ &protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ Type_descriptor_, &Type::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ Field_descriptor_, &Field::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ Enum_descriptor_, &Enum::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ EnumValue_descriptor_, &EnumValue::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ Option_descriptor_, &Option::default_instance());
+}
+
+} // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto() {
+ delete Type::default_instance_;
+ delete Type_reflection_;
+ delete Field::default_instance_;
+ delete Field_reflection_;
+ delete Enum::default_instance_;
+ delete Enum_reflection_;
+ delete EnumValue::default_instance_;
+ delete EnumValue_reflection_;
+ delete Option::default_instance_;
+ delete Option_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto() {
+ static bool already_here = false;
+ if (already_here) return;
+ already_here = true;
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
+ ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
+ ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+ "\n\032google/protobuf/type.proto\022\017google.pro"
+ "tobuf\032\031google/protobuf/any.proto\032$google"
+ "/protobuf/source_context.proto\"\256\001\n\004Type\022"
+ "\014\n\004name\030\001 \001(\t\022&\n\006fields\030\002 \003(\0132\026.google.p"
+ "rotobuf.Field\022\016\n\006oneofs\030\003 \003(\t\022(\n\007options"
+ "\030\004 \003(\0132\027.google.protobuf.Option\0226\n\016sourc"
+ "e_context\030\005 \001(\0132\036.google.protobuf.Source"
+ "Context\"\233\005\n\005Field\022)\n\004kind\030\001 \001(\0162\033.google"
+ ".protobuf.Field.Kind\0227\n\013cardinality\030\002 \001("
+ "\0162\".google.protobuf.Field.Cardinality\022\016\n"
+ "\006number\030\003 \001(\005\022\014\n\004name\030\004 \001(\t\022\020\n\010type_url\030"
+ "\006 \001(\t\022\023\n\013oneof_index\030\007 \001(\005\022\016\n\006packed\030\010 \001"
+ "(\010\022(\n\007options\030\t \003(\0132\027.google.protobuf.Op"
+ "tion\"\270\002\n\004Kind\022\020\n\014TYPE_UNKNOWN\020\000\022\017\n\013TYPE_"
+ "DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003"
+ "\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYP"
+ "E_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_BO"
+ "OL\020\010\022\017\n\013TYPE_STRING\020\t\022\020\n\014TYPE_MESSAGE\020\013\022"
+ "\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE"
+ "_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rTYPE_SFIXE"
+ "D64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_SINT64\020\022\""
+ "t\n\013Cardinality\022\027\n\023CARDINALITY_UNKNOWN\020\000\022"
+ "\030\n\024CARDINALITY_OPTIONAL\020\001\022\030\n\024CARDINALITY"
+ "_REQUIRED\020\002\022\030\n\024CARDINALITY_REPEATED\020\003\"\245\001"
+ "\n\004Enum\022\014\n\004name\030\001 \001(\t\022-\n\tenumvalue\030\002 \003(\0132"
+ "\032.google.protobuf.EnumValue\022(\n\007options\030\003"
+ " \003(\0132\027.google.protobuf.Option\0226\n\016source_"
+ "context\030\004 \001(\0132\036.google.protobuf.SourceCo"
+ "ntext\"S\n\tEnumValue\022\014\n\004name\030\001 \001(\t\022\016\n\006numb"
+ "er\030\002 \001(\005\022(\n\007options\030\003 \003(\0132\027.google.proto"
+ "buf.Option\";\n\006Option\022\014\n\004name\030\001 \001(\t\022#\n\005va"
+ "lue\030\002 \001(\0132\024.google.protobuf.AnyBI\n\023com.g"
+ "oogle.protobufB\tTypeProtoP\001\242\002\003GPB\252\002\036Goog"
+ "le.Protobuf.WellKnownTypesb\006proto3", 1354);
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+ "google/protobuf/type.proto", &protobuf_RegisterTypes);
+ Type::default_instance_ = new Type();
+ Field::default_instance_ = new Field();
+ Enum::default_instance_ = new Enum();
+ EnumValue::default_instance_ = new EnumValue();
+ Option::default_instance_ = new Option();
+ Type::default_instance_->InitAsDefaultInstance();
+ Field::default_instance_->InitAsDefaultInstance();
+ Enum::default_instance_->InitAsDefaultInstance();
+ EnumValue::default_instance_->InitAsDefaultInstance();
+ Option::default_instance_->InitAsDefaultInstance();
+ ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2ftype_2eproto {
+ StaticDescriptorInitializer_google_2fprotobuf_2ftype_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+ }
+} static_descriptor_initializer_google_2fprotobuf_2ftype_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+ GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+} // namespace
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int Type::kNameFieldNumber;
+const int Type::kFieldsFieldNumber;
+const int Type::kOneofsFieldNumber;
+const int Type::kOptionsFieldNumber;
+const int Type::kSourceContextFieldNumber;
+#endif // !_MSC_VER
+
+Type::Type()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.Type)
+}
+
+void Type::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+ source_context_ = const_cast< ::google::protobuf::SourceContext*>(&::google::protobuf::SourceContext::default_instance());
+}
+
+Type::Type(const Type& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.Type)
+}
+
+void Type::SharedCtor() {
+ _is_default_instance_ = false;
+ ::google::protobuf::internal::GetEmptyString();
+ _cached_size_ = 0;
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ source_context_ = NULL;
+}
+
+Type::~Type() {
+ // @@protoc_insertion_point(destructor:google.protobuf.Type)
+ SharedDtor();
+}
+
+void Type::SharedDtor() {
+ name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (this != default_instance_) {
+ delete source_context_;
+ }
+}
+
+void Type::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Type::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Type_descriptor_;
+}
+
+const Type& Type::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+ return *default_instance_;
+}
+
+Type* Type::default_instance_ = NULL;
+
+Type* Type::New(::google::protobuf::Arena* arena) const {
+ Type* n = new Type;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void Type::Clear() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+ source_context_ = NULL;
+ fields_.Clear();
+ oneofs_.Clear();
+ options_.Clear();
+}
+
+bool Type::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.Type)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional string name = 1;
+ case 1: {
+ if (tag == 10) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.Type.name");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(18)) goto parse_fields;
+ break;
+ }
+
+ // repeated .google.protobuf.Field fields = 2;
+ case 2: {
+ if (tag == 18) {
+ parse_fields:
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_fields:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ input, add_fields()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(18)) goto parse_loop_fields;
+ input->UnsafeDecrementRecursionDepth();
+ if (input->ExpectTag(26)) goto parse_oneofs;
+ break;
+ }
+
+ // repeated string oneofs = 3;
+ case 3: {
+ if (tag == 26) {
+ parse_oneofs:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->add_oneofs()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->oneofs(this->oneofs_size() - 1).data(),
+ this->oneofs(this->oneofs_size() - 1).length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.Type.oneofs");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(26)) goto parse_oneofs;
+ if (input->ExpectTag(34)) goto parse_options;
+ break;
+ }
+
+ // repeated .google.protobuf.Option options = 4;
+ case 4: {
+ if (tag == 34) {
+ parse_options:
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ input, add_options()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(34)) goto parse_loop_options;
+ input->UnsafeDecrementRecursionDepth();
+ if (input->ExpectTag(42)) goto parse_source_context;
+ break;
+ }
+
+ // optional .google.protobuf.SourceContext source_context = 5;
+ case 5: {
+ if (tag == 42) {
+ parse_source_context:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_source_context()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.Type)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.Type)
+ return false;
+#undef DO_
+}
+
+void Type::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.Type)
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Type.name");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 1, this->name(), output);
+ }
+
+ // repeated .google.protobuf.Field fields = 2;
+ for (unsigned int i = 0, n = this->fields_size(); i < n; i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 2, this->fields(i), output);
+ }
+
+ // repeated string oneofs = 3;
+ for (int i = 0; i < this->oneofs_size(); i++) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->oneofs(i).data(), this->oneofs(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Type.oneofs");
+ ::google::protobuf::internal::WireFormatLite::WriteString(
+ 3, this->oneofs(i), output);
+ }
+
+ // repeated .google.protobuf.Option options = 4;
+ for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 4, this->options(i), output);
+ }
+
+ // optional .google.protobuf.SourceContext source_context = 5;
+ if (this->has_source_context()) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 5, *this->source_context_, output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.Type)
+}
+
+::google::protobuf::uint8* Type::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Type)
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Type.name");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 1, this->name(), target);
+ }
+
+ // repeated .google.protobuf.Field fields = 2;
+ for (unsigned int i = 0, n = this->fields_size(); i < n; i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 2, this->fields(i), target);
+ }
+
+ // repeated string oneofs = 3;
+ for (int i = 0; i < this->oneofs_size(); i++) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->oneofs(i).data(), this->oneofs(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Type.oneofs");
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteStringToArray(3, this->oneofs(i), target);
+ }
+
+ // repeated .google.protobuf.Option options = 4;
+ for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 4, this->options(i), target);
+ }
+
+ // optional .google.protobuf.SourceContext source_context = 5;
+ if (this->has_source_context()) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 5, *this->source_context_, target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Type)
+ return target;
+}
+
+int Type::ByteSize() const {
+ int total_size = 0;
+
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->name());
+ }
+
+ // optional .google.protobuf.SourceContext source_context = 5;
+ if (this->has_source_context()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ *this->source_context_);
+ }
+
+ // repeated .google.protobuf.Field fields = 2;
+ total_size += 1 * this->fields_size();
+ for (int i = 0; i < this->fields_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->fields(i));
+ }
+
+ // repeated string oneofs = 3;
+ total_size += 1 * this->oneofs_size();
+ for (int i = 0; i < this->oneofs_size(); i++) {
+ total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->oneofs(i));
+ }
+
+ // repeated .google.protobuf.Option options = 4;
+ total_size += 1 * this->options_size();
+ for (int i = 0; i < this->options_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->options(i));
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void Type::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const Type* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Type>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void Type::MergeFrom(const Type& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ fields_.MergeFrom(from.fields_);
+ oneofs_.MergeFrom(from.oneofs_);
+ options_.MergeFrom(from.options_);
+ if (from.name().size() > 0) {
+
+ name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+ }
+ if (from.has_source_context()) {
+ mutable_source_context()->::google::protobuf::SourceContext::MergeFrom(from.source_context());
+ }
+}
+
+void Type::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void Type::CopyFrom(const Type& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Type::IsInitialized() const {
+
+ return true;
+}
+
+void Type::Swap(Type* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void Type::InternalSwap(Type* other) {
+ name_.Swap(&other->name_);
+ fields_.UnsafeArenaSwap(&other->fields_);
+ oneofs_.UnsafeArenaSwap(&other->oneofs_);
+ options_.UnsafeArenaSwap(&other->options_);
+ std::swap(source_context_, other->source_context_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Type::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = Type_descriptor_;
+ metadata.reflection = Type_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Type
+
+// optional string name = 1;
+void Type::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Type::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Type.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Type::set_name(const ::std::string& value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Type.name)
+}
+ void Type::set_name(const char* value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Type.name)
+}
+ void Type::set_name(const char* value, size_t size) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.name)
+}
+ ::std::string* Type::mutable_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Type.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Type::release_name() {
+
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Type::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+
+ } else {
+
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Type.name)
+}
+
+// repeated .google.protobuf.Field fields = 2;
+int Type::fields_size() const {
+ return fields_.size();
+}
+void Type::clear_fields() {
+ fields_.Clear();
+}
+ const ::google::protobuf::Field& Type::fields(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Type.fields)
+ return fields_.Get(index);
+}
+ ::google::protobuf::Field* Type::mutable_fields(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Type.fields)
+ return fields_.Mutable(index);
+}
+ ::google::protobuf::Field* Type::add_fields() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Type.fields)
+ return fields_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >&
+Type::fields() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Type.fields)
+ return fields_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >*
+Type::mutable_fields() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.fields)
+ return &fields_;
+}
+
+// repeated string oneofs = 3;
+int Type::oneofs_size() const {
+ return oneofs_.size();
+}
+void Type::clear_oneofs() {
+ oneofs_.Clear();
+}
+ const ::std::string& Type::oneofs(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Type.oneofs)
+ return oneofs_.Get(index);
+}
+ ::std::string* Type::mutable_oneofs(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Type.oneofs)
+ return oneofs_.Mutable(index);
+}
+ void Type::set_oneofs(int index, const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.Type.oneofs)
+ oneofs_.Mutable(index)->assign(value);
+}
+ void Type::set_oneofs(int index, const char* value) {
+ oneofs_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Type.oneofs)
+}
+ void Type::set_oneofs(int index, const char* value, size_t size) {
+ oneofs_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.oneofs)
+}
+ ::std::string* Type::add_oneofs() {
+ return oneofs_.Add();
+}
+ void Type::add_oneofs(const ::std::string& value) {
+ oneofs_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.Type.oneofs)
+}
+ void Type::add_oneofs(const char* value) {
+ oneofs_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.Type.oneofs)
+}
+ void Type::add_oneofs(const char* value, size_t size) {
+ oneofs_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.Type.oneofs)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+Type::oneofs() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Type.oneofs)
+ return oneofs_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+Type::mutable_oneofs() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.oneofs)
+ return &oneofs_;
+}
+
+// repeated .google.protobuf.Option options = 4;
+int Type::options_size() const {
+ return options_.size();
+}
+void Type::clear_options() {
+ options_.Clear();
+}
+ const ::google::protobuf::Option& Type::options(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Type.options)
+ return options_.Get(index);
+}
+ ::google::protobuf::Option* Type::mutable_options(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Type.options)
+ return options_.Mutable(index);
+}
+ ::google::protobuf::Option* Type::add_options() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Type.options)
+ return options_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Type::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Type.options)
+ return options_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Type::mutable_options() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.options)
+ return &options_;
+}
+
+// optional .google.protobuf.SourceContext source_context = 5;
+bool Type::has_source_context() const {
+ return !_is_default_instance_ && source_context_ != NULL;
+}
+void Type::clear_source_context() {
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+ source_context_ = NULL;
+}
+ const ::google::protobuf::SourceContext& Type::source_context() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Type.source_context)
+ return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
+}
+ ::google::protobuf::SourceContext* Type::mutable_source_context() {
+
+ if (source_context_ == NULL) {
+ source_context_ = new ::google::protobuf::SourceContext;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Type.source_context)
+ return source_context_;
+}
+ ::google::protobuf::SourceContext* Type::release_source_context() {
+
+ ::google::protobuf::SourceContext* temp = source_context_;
+ source_context_ = NULL;
+ return temp;
+}
+ void Type::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
+ delete source_context_;
+ source_context_ = source_context;
+ if (source_context) {
+
+ } else {
+
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Type.source_context)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+const ::google::protobuf::EnumDescriptor* Field_Kind_descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Field_Kind_descriptor_;
+}
+bool Field_Kind_IsValid(int value) {
+ switch(value) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ return true;
+ default:
+ return false;
+ }
+}
+
+#ifndef _MSC_VER
+const Field_Kind Field::TYPE_UNKNOWN;
+const Field_Kind Field::TYPE_DOUBLE;
+const Field_Kind Field::TYPE_FLOAT;
+const Field_Kind Field::TYPE_INT64;
+const Field_Kind Field::TYPE_UINT64;
+const Field_Kind Field::TYPE_INT32;
+const Field_Kind Field::TYPE_FIXED64;
+const Field_Kind Field::TYPE_FIXED32;
+const Field_Kind Field::TYPE_BOOL;
+const Field_Kind Field::TYPE_STRING;
+const Field_Kind Field::TYPE_MESSAGE;
+const Field_Kind Field::TYPE_BYTES;
+const Field_Kind Field::TYPE_UINT32;
+const Field_Kind Field::TYPE_ENUM;
+const Field_Kind Field::TYPE_SFIXED32;
+const Field_Kind Field::TYPE_SFIXED64;
+const Field_Kind Field::TYPE_SINT32;
+const Field_Kind Field::TYPE_SINT64;
+const Field_Kind Field::Kind_MIN;
+const Field_Kind Field::Kind_MAX;
+const int Field::Kind_ARRAYSIZE;
+#endif // _MSC_VER
+const ::google::protobuf::EnumDescriptor* Field_Cardinality_descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Field_Cardinality_descriptor_;
+}
+bool Field_Cardinality_IsValid(int value) {
+ switch(value) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ return true;
+ default:
+ return false;
+ }
+}
+
+#ifndef _MSC_VER
+const Field_Cardinality Field::CARDINALITY_UNKNOWN;
+const Field_Cardinality Field::CARDINALITY_OPTIONAL;
+const Field_Cardinality Field::CARDINALITY_REQUIRED;
+const Field_Cardinality Field::CARDINALITY_REPEATED;
+const Field_Cardinality Field::Cardinality_MIN;
+const Field_Cardinality Field::Cardinality_MAX;
+const int Field::Cardinality_ARRAYSIZE;
+#endif // _MSC_VER
+#ifndef _MSC_VER
+const int Field::kKindFieldNumber;
+const int Field::kCardinalityFieldNumber;
+const int Field::kNumberFieldNumber;
+const int Field::kNameFieldNumber;
+const int Field::kTypeUrlFieldNumber;
+const int Field::kOneofIndexFieldNumber;
+const int Field::kPackedFieldNumber;
+const int Field::kOptionsFieldNumber;
+#endif // !_MSC_VER
+
+Field::Field()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.Field)
+}
+
+void Field::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+Field::Field(const Field& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.Field)
+}
+
+void Field::SharedCtor() {
+ _is_default_instance_ = false;
+ ::google::protobuf::internal::GetEmptyString();
+ _cached_size_ = 0;
+ kind_ = 0;
+ cardinality_ = 0;
+ number_ = 0;
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ oneof_index_ = 0;
+ packed_ = false;
+}
+
+Field::~Field() {
+ // @@protoc_insertion_point(destructor:google.protobuf.Field)
+ SharedDtor();
+}
+
+void Field::SharedDtor() {
+ name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ type_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (this != default_instance_) {
+ }
+}
+
+void Field::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Field::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Field_descriptor_;
+}
+
+const Field& Field::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+ return *default_instance_;
+}
+
+Field* Field::default_instance_ = NULL;
+
+Field* Field::New(::google::protobuf::Arena* arena) const {
+ Field* n = new Field;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void Field::Clear() {
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<Field*>(16)->f)
+
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+ ZR_(kind_, cardinality_);
+ ZR_(number_, oneof_index_);
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ packed_ = false;
+
+#undef ZR_HELPER_
+#undef ZR_
+
+ options_.Clear();
+}
+
+bool Field::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.Field)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional .google.protobuf.Field.Kind kind = 1;
+ case 1: {
+ if (tag == 8) {
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ set_kind(static_cast< ::google::protobuf::Field_Kind >(value));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(16)) goto parse_cardinality;
+ break;
+ }
+
+ // optional .google.protobuf.Field.Cardinality cardinality = 2;
+ case 2: {
+ if (tag == 16) {
+ parse_cardinality:
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ set_cardinality(static_cast< ::google::protobuf::Field_Cardinality >(value));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(24)) goto parse_number;
+ break;
+ }
+
+ // optional int32 number = 3;
+ case 3: {
+ if (tag == 24) {
+ parse_number:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &number_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(34)) goto parse_name;
+ break;
+ }
+
+ // optional string name = 4;
+ case 4: {
+ if (tag == 34) {
+ parse_name:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.Field.name");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(50)) goto parse_type_url;
+ break;
+ }
+
+ // optional string type_url = 6;
+ case 6: {
+ if (tag == 50) {
+ parse_type_url:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_type_url()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->type_url().data(), this->type_url().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.Field.type_url");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(56)) goto parse_oneof_index;
+ break;
+ }
+
+ // optional int32 oneof_index = 7;
+ case 7: {
+ if (tag == 56) {
+ parse_oneof_index:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &oneof_index_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(64)) goto parse_packed;
+ break;
+ }
+
+ // optional bool packed = 8;
+ case 8: {
+ if (tag == 64) {
+ parse_packed:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &packed_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(74)) goto parse_options;
+ break;
+ }
+
+ // repeated .google.protobuf.Option options = 9;
+ case 9: {
+ if (tag == 74) {
+ parse_options:
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ input, add_options()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(74)) goto parse_loop_options;
+ input->UnsafeDecrementRecursionDepth();
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.Field)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.Field)
+ return false;
+#undef DO_
+}
+
+void Field::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.Field)
+ // optional .google.protobuf.Field.Kind kind = 1;
+ if (this->kind() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteEnum(
+ 1, this->kind(), output);
+ }
+
+ // optional .google.protobuf.Field.Cardinality cardinality = 2;
+ if (this->cardinality() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteEnum(
+ 2, this->cardinality(), output);
+ }
+
+ // optional int32 number = 3;
+ if (this->number() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->number(), output);
+ }
+
+ // optional string name = 4;
+ if (this->name().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Field.name");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 4, this->name(), output);
+ }
+
+ // optional string type_url = 6;
+ if (this->type_url().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->type_url().data(), this->type_url().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Field.type_url");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 6, this->type_url(), output);
+ }
+
+ // optional int32 oneof_index = 7;
+ if (this->oneof_index() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(7, this->oneof_index(), output);
+ }
+
+ // optional bool packed = 8;
+ if (this->packed() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(8, this->packed(), output);
+ }
+
+ // repeated .google.protobuf.Option options = 9;
+ for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 9, this->options(i), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.Field)
+}
+
+::google::protobuf::uint8* Field::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Field)
+ // optional .google.protobuf.Field.Kind kind = 1;
+ if (this->kind() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+ 1, this->kind(), target);
+ }
+
+ // optional .google.protobuf.Field.Cardinality cardinality = 2;
+ if (this->cardinality() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+ 2, this->cardinality(), target);
+ }
+
+ // optional int32 number = 3;
+ if (this->number() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->number(), target);
+ }
+
+ // optional string name = 4;
+ if (this->name().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Field.name");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 4, this->name(), target);
+ }
+
+ // optional string type_url = 6;
+ if (this->type_url().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->type_url().data(), this->type_url().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Field.type_url");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 6, this->type_url(), target);
+ }
+
+ // optional int32 oneof_index = 7;
+ if (this->oneof_index() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(7, this->oneof_index(), target);
+ }
+
+ // optional bool packed = 8;
+ if (this->packed() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(8, this->packed(), target);
+ }
+
+ // repeated .google.protobuf.Option options = 9;
+ for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 9, this->options(i), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Field)
+ return target;
+}
+
+int Field::ByteSize() const {
+ int total_size = 0;
+
+ // optional .google.protobuf.Field.Kind kind = 1;
+ if (this->kind() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::EnumSize(this->kind());
+ }
+
+ // optional .google.protobuf.Field.Cardinality cardinality = 2;
+ if (this->cardinality() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::EnumSize(this->cardinality());
+ }
+
+ // optional int32 number = 3;
+ if (this->number() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->number());
+ }
+
+ // optional string name = 4;
+ if (this->name().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->name());
+ }
+
+ // optional string type_url = 6;
+ if (this->type_url().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->type_url());
+ }
+
+ // optional int32 oneof_index = 7;
+ if (this->oneof_index() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->oneof_index());
+ }
+
+ // optional bool packed = 8;
+ if (this->packed() != 0) {
+ total_size += 1 + 1;
+ }
+
+ // repeated .google.protobuf.Option options = 9;
+ total_size += 1 * this->options_size();
+ for (int i = 0; i < this->options_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->options(i));
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void Field::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const Field* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Field>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void Field::MergeFrom(const Field& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ options_.MergeFrom(from.options_);
+ if (from.kind() != 0) {
+ set_kind(from.kind());
+ }
+ if (from.cardinality() != 0) {
+ set_cardinality(from.cardinality());
+ }
+ if (from.number() != 0) {
+ set_number(from.number());
+ }
+ if (from.name().size() > 0) {
+
+ name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+ }
+ if (from.type_url().size() > 0) {
+
+ type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_);
+ }
+ if (from.oneof_index() != 0) {
+ set_oneof_index(from.oneof_index());
+ }
+ if (from.packed() != 0) {
+ set_packed(from.packed());
+ }
+}
+
+void Field::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void Field::CopyFrom(const Field& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Field::IsInitialized() const {
+
+ return true;
+}
+
+void Field::Swap(Field* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void Field::InternalSwap(Field* other) {
+ std::swap(kind_, other->kind_);
+ std::swap(cardinality_, other->cardinality_);
+ std::swap(number_, other->number_);
+ name_.Swap(&other->name_);
+ type_url_.Swap(&other->type_url_);
+ std::swap(oneof_index_, other->oneof_index_);
+ std::swap(packed_, other->packed_);
+ options_.UnsafeArenaSwap(&other->options_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Field::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = Field_descriptor_;
+ metadata.reflection = Field_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Field
+
+// optional .google.protobuf.Field.Kind kind = 1;
+void Field::clear_kind() {
+ kind_ = 0;
+}
+ ::google::protobuf::Field_Kind Field::kind() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.kind)
+ return static_cast< ::google::protobuf::Field_Kind >(kind_);
+}
+ void Field::set_kind(::google::protobuf::Field_Kind value) {
+
+ kind_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Field.kind)
+}
+
+// optional .google.protobuf.Field.Cardinality cardinality = 2;
+void Field::clear_cardinality() {
+ cardinality_ = 0;
+}
+ ::google::protobuf::Field_Cardinality Field::cardinality() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.cardinality)
+ return static_cast< ::google::protobuf::Field_Cardinality >(cardinality_);
+}
+ void Field::set_cardinality(::google::protobuf::Field_Cardinality value) {
+
+ cardinality_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Field.cardinality)
+}
+
+// optional int32 number = 3;
+void Field::clear_number() {
+ number_ = 0;
+}
+ ::google::protobuf::int32 Field::number() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.number)
+ return number_;
+}
+ void Field::set_number(::google::protobuf::int32 value) {
+
+ number_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Field.number)
+}
+
+// optional string name = 4;
+void Field::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Field::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Field::set_name(const ::std::string& value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Field.name)
+}
+ void Field::set_name(const char* value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Field.name)
+}
+ void Field::set_name(const char* value, size_t size) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.name)
+}
+ ::std::string* Field::mutable_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Field.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Field::release_name() {
+
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Field::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+
+ } else {
+
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.name)
+}
+
+// optional string type_url = 6;
+void Field::clear_type_url() {
+ type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Field::type_url() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.type_url)
+ return type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Field::set_type_url(const ::std::string& value) {
+
+ type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Field.type_url)
+}
+ void Field::set_type_url(const char* value) {
+
+ type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Field.type_url)
+}
+ void Field::set_type_url(const char* value, size_t size) {
+
+ type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.type_url)
+}
+ ::std::string* Field::mutable_type_url() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Field.type_url)
+ return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Field::release_type_url() {
+
+ return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Field::set_allocated_type_url(::std::string* type_url) {
+ if (type_url != NULL) {
+
+ } else {
+
+ }
+ type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_url);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.type_url)
+}
+
+// optional int32 oneof_index = 7;
+void Field::clear_oneof_index() {
+ oneof_index_ = 0;
+}
+ ::google::protobuf::int32 Field::oneof_index() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.oneof_index)
+ return oneof_index_;
+}
+ void Field::set_oneof_index(::google::protobuf::int32 value) {
+
+ oneof_index_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Field.oneof_index)
+}
+
+// optional bool packed = 8;
+void Field::clear_packed() {
+ packed_ = false;
+}
+ bool Field::packed() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.packed)
+ return packed_;
+}
+ void Field::set_packed(bool value) {
+
+ packed_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Field.packed)
+}
+
+// repeated .google.protobuf.Option options = 9;
+int Field::options_size() const {
+ return options_.size();
+}
+void Field::clear_options() {
+ options_.Clear();
+}
+ const ::google::protobuf::Option& Field::options(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.options)
+ return options_.Get(index);
+}
+ ::google::protobuf::Option* Field::mutable_options(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Field.options)
+ return options_.Mutable(index);
+}
+ ::google::protobuf::Option* Field::add_options() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Field.options)
+ return options_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Field::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Field.options)
+ return options_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Field::mutable_options() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Field.options)
+ return &options_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int Enum::kNameFieldNumber;
+const int Enum::kEnumvalueFieldNumber;
+const int Enum::kOptionsFieldNumber;
+const int Enum::kSourceContextFieldNumber;
+#endif // !_MSC_VER
+
+Enum::Enum()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.Enum)
+}
+
+void Enum::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+ source_context_ = const_cast< ::google::protobuf::SourceContext*>(&::google::protobuf::SourceContext::default_instance());
+}
+
+Enum::Enum(const Enum& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.Enum)
+}
+
+void Enum::SharedCtor() {
+ _is_default_instance_ = false;
+ ::google::protobuf::internal::GetEmptyString();
+ _cached_size_ = 0;
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ source_context_ = NULL;
+}
+
+Enum::~Enum() {
+ // @@protoc_insertion_point(destructor:google.protobuf.Enum)
+ SharedDtor();
+}
+
+void Enum::SharedDtor() {
+ name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (this != default_instance_) {
+ delete source_context_;
+ }
+}
+
+void Enum::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Enum::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Enum_descriptor_;
+}
+
+const Enum& Enum::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+ return *default_instance_;
+}
+
+Enum* Enum::default_instance_ = NULL;
+
+Enum* Enum::New(::google::protobuf::Arena* arena) const {
+ Enum* n = new Enum;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void Enum::Clear() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+ source_context_ = NULL;
+ enumvalue_.Clear();
+ options_.Clear();
+}
+
+bool Enum::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.Enum)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional string name = 1;
+ case 1: {
+ if (tag == 10) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.Enum.name");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(18)) goto parse_enumvalue;
+ break;
+ }
+
+ // repeated .google.protobuf.EnumValue enumvalue = 2;
+ case 2: {
+ if (tag == 18) {
+ parse_enumvalue:
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_enumvalue:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ input, add_enumvalue()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(18)) goto parse_loop_enumvalue;
+ if (input->ExpectTag(26)) goto parse_loop_options;
+ input->UnsafeDecrementRecursionDepth();
+ break;
+ }
+
+ // repeated .google.protobuf.Option options = 3;
+ case 3: {
+ if (tag == 26) {
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ input, add_options()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(26)) goto parse_loop_options;
+ input->UnsafeDecrementRecursionDepth();
+ if (input->ExpectTag(34)) goto parse_source_context;
+ break;
+ }
+
+ // optional .google.protobuf.SourceContext source_context = 4;
+ case 4: {
+ if (tag == 34) {
+ parse_source_context:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_source_context()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.Enum)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.Enum)
+ return false;
+#undef DO_
+}
+
+void Enum::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.Enum)
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Enum.name");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 1, this->name(), output);
+ }
+
+ // repeated .google.protobuf.EnumValue enumvalue = 2;
+ for (unsigned int i = 0, n = this->enumvalue_size(); i < n; i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 2, this->enumvalue(i), output);
+ }
+
+ // repeated .google.protobuf.Option options = 3;
+ for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 3, this->options(i), output);
+ }
+
+ // optional .google.protobuf.SourceContext source_context = 4;
+ if (this->has_source_context()) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 4, *this->source_context_, output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.Enum)
+}
+
+::google::protobuf::uint8* Enum::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Enum)
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Enum.name");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 1, this->name(), target);
+ }
+
+ // repeated .google.protobuf.EnumValue enumvalue = 2;
+ for (unsigned int i = 0, n = this->enumvalue_size(); i < n; i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 2, this->enumvalue(i), target);
+ }
+
+ // repeated .google.protobuf.Option options = 3;
+ for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 3, this->options(i), target);
+ }
+
+ // optional .google.protobuf.SourceContext source_context = 4;
+ if (this->has_source_context()) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 4, *this->source_context_, target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Enum)
+ return target;
+}
+
+int Enum::ByteSize() const {
+ int total_size = 0;
+
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->name());
+ }
+
+ // optional .google.protobuf.SourceContext source_context = 4;
+ if (this->has_source_context()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ *this->source_context_);
+ }
+
+ // repeated .google.protobuf.EnumValue enumvalue = 2;
+ total_size += 1 * this->enumvalue_size();
+ for (int i = 0; i < this->enumvalue_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->enumvalue(i));
+ }
+
+ // repeated .google.protobuf.Option options = 3;
+ total_size += 1 * this->options_size();
+ for (int i = 0; i < this->options_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->options(i));
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void Enum::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const Enum* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Enum>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void Enum::MergeFrom(const Enum& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ enumvalue_.MergeFrom(from.enumvalue_);
+ options_.MergeFrom(from.options_);
+ if (from.name().size() > 0) {
+
+ name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+ }
+ if (from.has_source_context()) {
+ mutable_source_context()->::google::protobuf::SourceContext::MergeFrom(from.source_context());
+ }
+}
+
+void Enum::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void Enum::CopyFrom(const Enum& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Enum::IsInitialized() const {
+
+ return true;
+}
+
+void Enum::Swap(Enum* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void Enum::InternalSwap(Enum* other) {
+ name_.Swap(&other->name_);
+ enumvalue_.UnsafeArenaSwap(&other->enumvalue_);
+ options_.UnsafeArenaSwap(&other->options_);
+ std::swap(source_context_, other->source_context_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Enum::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = Enum_descriptor_;
+ metadata.reflection = Enum_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Enum
+
+// optional string name = 1;
+void Enum::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Enum::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Enum.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Enum::set_name(const ::std::string& value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Enum.name)
+}
+ void Enum::set_name(const char* value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Enum.name)
+}
+ void Enum::set_name(const char* value, size_t size) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Enum.name)
+}
+ ::std::string* Enum::mutable_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Enum::release_name() {
+
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Enum::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+
+ } else {
+
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Enum.name)
+}
+
+// repeated .google.protobuf.EnumValue enumvalue = 2;
+int Enum::enumvalue_size() const {
+ return enumvalue_.size();
+}
+void Enum::clear_enumvalue() {
+ enumvalue_.Clear();
+}
+ const ::google::protobuf::EnumValue& Enum::enumvalue(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Enum.enumvalue)
+ return enumvalue_.Get(index);
+}
+ ::google::protobuf::EnumValue* Enum::mutable_enumvalue(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.enumvalue)
+ return enumvalue_.Mutable(index);
+}
+ ::google::protobuf::EnumValue* Enum::add_enumvalue() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Enum.enumvalue)
+ return enumvalue_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >&
+Enum::enumvalue() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Enum.enumvalue)
+ return enumvalue_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >*
+Enum::mutable_enumvalue() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Enum.enumvalue)
+ return &enumvalue_;
+}
+
+// repeated .google.protobuf.Option options = 3;
+int Enum::options_size() const {
+ return options_.size();
+}
+void Enum::clear_options() {
+ options_.Clear();
+}
+ const ::google::protobuf::Option& Enum::options(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Enum.options)
+ return options_.Get(index);
+}
+ ::google::protobuf::Option* Enum::mutable_options(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.options)
+ return options_.Mutable(index);
+}
+ ::google::protobuf::Option* Enum::add_options() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Enum.options)
+ return options_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Enum::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Enum.options)
+ return options_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Enum::mutable_options() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Enum.options)
+ return &options_;
+}
+
+// optional .google.protobuf.SourceContext source_context = 4;
+bool Enum::has_source_context() const {
+ return !_is_default_instance_ && source_context_ != NULL;
+}
+void Enum::clear_source_context() {
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+ source_context_ = NULL;
+}
+ const ::google::protobuf::SourceContext& Enum::source_context() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Enum.source_context)
+ return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
+}
+ ::google::protobuf::SourceContext* Enum::mutable_source_context() {
+
+ if (source_context_ == NULL) {
+ source_context_ = new ::google::protobuf::SourceContext;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.source_context)
+ return source_context_;
+}
+ ::google::protobuf::SourceContext* Enum::release_source_context() {
+
+ ::google::protobuf::SourceContext* temp = source_context_;
+ source_context_ = NULL;
+ return temp;
+}
+ void Enum::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
+ delete source_context_;
+ source_context_ = source_context;
+ if (source_context) {
+
+ } else {
+
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Enum.source_context)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int EnumValue::kNameFieldNumber;
+const int EnumValue::kNumberFieldNumber;
+const int EnumValue::kOptionsFieldNumber;
+#endif // !_MSC_VER
+
+EnumValue::EnumValue()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.EnumValue)
+}
+
+void EnumValue::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+EnumValue::EnumValue(const EnumValue& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValue)
+}
+
+void EnumValue::SharedCtor() {
+ _is_default_instance_ = false;
+ ::google::protobuf::internal::GetEmptyString();
+ _cached_size_ = 0;
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ number_ = 0;
+}
+
+EnumValue::~EnumValue() {
+ // @@protoc_insertion_point(destructor:google.protobuf.EnumValue)
+ SharedDtor();
+}
+
+void EnumValue::SharedDtor() {
+ name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (this != default_instance_) {
+ }
+}
+
+void EnumValue::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* EnumValue::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return EnumValue_descriptor_;
+}
+
+const EnumValue& EnumValue::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+ return *default_instance_;
+}
+
+EnumValue* EnumValue::default_instance_ = NULL;
+
+EnumValue* EnumValue::New(::google::protobuf::Arena* arena) const {
+ EnumValue* n = new EnumValue;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void EnumValue::Clear() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ number_ = 0;
+ options_.Clear();
+}
+
+bool EnumValue::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.EnumValue)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional string name = 1;
+ case 1: {
+ if (tag == 10) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.EnumValue.name");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(16)) goto parse_number;
+ break;
+ }
+
+ // optional int32 number = 2;
+ case 2: {
+ if (tag == 16) {
+ parse_number:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &number_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(26)) goto parse_options;
+ break;
+ }
+
+ // repeated .google.protobuf.Option options = 3;
+ case 3: {
+ if (tag == 26) {
+ parse_options:
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ input, add_options()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(26)) goto parse_loop_options;
+ input->UnsafeDecrementRecursionDepth();
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.EnumValue)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.EnumValue)
+ return false;
+#undef DO_
+}
+
+void EnumValue::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.EnumValue)
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.EnumValue.name");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 1, this->name(), output);
+ }
+
+ // optional int32 number = 2;
+ if (this->number() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->number(), output);
+ }
+
+ // repeated .google.protobuf.Option options = 3;
+ for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 3, this->options(i), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.EnumValue)
+}
+
+::google::protobuf::uint8* EnumValue::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValue)
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.EnumValue.name");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 1, this->name(), target);
+ }
+
+ // optional int32 number = 2;
+ if (this->number() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->number(), target);
+ }
+
+ // repeated .google.protobuf.Option options = 3;
+ for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 3, this->options(i), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValue)
+ return target;
+}
+
+int EnumValue::ByteSize() const {
+ int total_size = 0;
+
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->name());
+ }
+
+ // optional int32 number = 2;
+ if (this->number() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->number());
+ }
+
+ // repeated .google.protobuf.Option options = 3;
+ total_size += 1 * this->options_size();
+ for (int i = 0; i < this->options_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->options(i));
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void EnumValue::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const EnumValue* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const EnumValue>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void EnumValue::MergeFrom(const EnumValue& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ options_.MergeFrom(from.options_);
+ if (from.name().size() > 0) {
+
+ name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+ }
+ if (from.number() != 0) {
+ set_number(from.number());
+ }
+}
+
+void EnumValue::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void EnumValue::CopyFrom(const EnumValue& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool EnumValue::IsInitialized() const {
+
+ return true;
+}
+
+void EnumValue::Swap(EnumValue* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void EnumValue::InternalSwap(EnumValue* other) {
+ name_.Swap(&other->name_);
+ std::swap(number_, other->number_);
+ options_.UnsafeArenaSwap(&other->options_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata EnumValue::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = EnumValue_descriptor_;
+ metadata.reflection = EnumValue_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumValue
+
+// optional string name = 1;
+void EnumValue::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& EnumValue::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumValue::set_name(const ::std::string& value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.name)
+}
+ void EnumValue::set_name(const char* value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValue.name)
+}
+ void EnumValue::set_name(const char* value, size_t size) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValue.name)
+}
+ ::std::string* EnumValue::mutable_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValue.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* EnumValue::release_name() {
+
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumValue::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+
+ } else {
+
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValue.name)
+}
+
+// optional int32 number = 2;
+void EnumValue::clear_number() {
+ number_ = 0;
+}
+ ::google::protobuf::int32 EnumValue::number() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.number)
+ return number_;
+}
+ void EnumValue::set_number(::google::protobuf::int32 value) {
+
+ number_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.number)
+}
+
+// repeated .google.protobuf.Option options = 3;
+int EnumValue::options_size() const {
+ return options_.size();
+}
+void EnumValue::clear_options() {
+ options_.Clear();
+}
+ const ::google::protobuf::Option& EnumValue::options(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.options)
+ return options_.Get(index);
+}
+ ::google::protobuf::Option* EnumValue::mutable_options(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValue.options)
+ return options_.Mutable(index);
+}
+ ::google::protobuf::Option* EnumValue::add_options() {
+ // @@protoc_insertion_point(field_add:google.protobuf.EnumValue.options)
+ return options_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+EnumValue::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumValue.options)
+ return options_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+EnumValue::mutable_options() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValue.options)
+ return &options_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int Option::kNameFieldNumber;
+const int Option::kValueFieldNumber;
+#endif // !_MSC_VER
+
+Option::Option()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.Option)
+}
+
+void Option::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+ value_ = const_cast< ::google::protobuf::Any*>(&::google::protobuf::Any::default_instance());
+}
+
+Option::Option(const Option& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.Option)
+}
+
+void Option::SharedCtor() {
+ _is_default_instance_ = false;
+ ::google::protobuf::internal::GetEmptyString();
+ _cached_size_ = 0;
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ value_ = NULL;
+}
+
+Option::~Option() {
+ // @@protoc_insertion_point(destructor:google.protobuf.Option)
+ SharedDtor();
+}
+
+void Option::SharedDtor() {
+ name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (this != default_instance_) {
+ delete value_;
+ }
+}
+
+void Option::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Option::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Option_descriptor_;
+}
+
+const Option& Option::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+ return *default_instance_;
+}
+
+Option* Option::default_instance_ = NULL;
+
+Option* Option::New(::google::protobuf::Arena* arena) const {
+ Option* n = new Option;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void Option::Clear() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_;
+ value_ = NULL;
+}
+
+bool Option::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.Option)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional string name = 1;
+ case 1: {
+ if (tag == 10) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.Option.name");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(18)) goto parse_value;
+ break;
+ }
+
+ // optional .google.protobuf.Any value = 2;
+ case 2: {
+ if (tag == 18) {
+ parse_value:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_value()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.Option)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.Option)
+ return false;
+#undef DO_
+}
+
+void Option::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.Option)
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Option.name");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 1, this->name(), output);
+ }
+
+ // optional .google.protobuf.Any value = 2;
+ if (this->has_value()) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 2, *this->value_, output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.Option)
+}
+
+::google::protobuf::uint8* Option::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Option)
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.Option.name");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 1, this->name(), target);
+ }
+
+ // optional .google.protobuf.Any value = 2;
+ if (this->has_value()) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 2, *this->value_, target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Option)
+ return target;
+}
+
+int Option::ByteSize() const {
+ int total_size = 0;
+
+ // optional string name = 1;
+ if (this->name().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->name());
+ }
+
+ // optional .google.protobuf.Any value = 2;
+ if (this->has_value()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ *this->value_);
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void Option::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const Option* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Option>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void Option::MergeFrom(const Option& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from.name().size() > 0) {
+
+ name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+ }
+ if (from.has_value()) {
+ mutable_value()->::google::protobuf::Any::MergeFrom(from.value());
+ }
+}
+
+void Option::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void Option::CopyFrom(const Option& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Option::IsInitialized() const {
+
+ return true;
+}
+
+void Option::Swap(Option* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void Option::InternalSwap(Option* other) {
+ name_.Swap(&other->name_);
+ std::swap(value_, other->value_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Option::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = Option_descriptor_;
+ metadata.reflection = Option_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Option
+
+// optional string name = 1;
+void Option::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& Option::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Option.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Option::set_name(const ::std::string& value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Option.name)
+}
+ void Option::set_name(const char* value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Option.name)
+}
+ void Option::set_name(const char* value, size_t size) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Option.name)
+}
+ ::std::string* Option::mutable_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Option.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* Option::release_name() {
+
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void Option::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+
+ } else {
+
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Option.name)
+}
+
+// optional .google.protobuf.Any value = 2;
+bool Option::has_value() const {
+ return !_is_default_instance_ && value_ != NULL;
+}
+void Option::clear_value() {
+ if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_;
+ value_ = NULL;
+}
+ const ::google::protobuf::Any& Option::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Option.value)
+ return value_ != NULL ? *value_ : *default_instance_->value_;
+}
+ ::google::protobuf::Any* Option::mutable_value() {
+
+ if (value_ == NULL) {
+ value_ = new ::google::protobuf::Any;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Option.value)
+ return value_;
+}
+ ::google::protobuf::Any* Option::release_value() {
+
+ ::google::protobuf::Any* temp = value_;
+ value_ = NULL;
+ return temp;
+}
+ void Option::set_allocated_value(::google::protobuf::Any* value) {
+ delete value_;
+ value_ = value;
+ if (value) {
+
+ } else {
+
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Option.value)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h
new file mode 100644
index 00000000..c9952efa
--- /dev/null
+++ b/src/google/protobuf/type.pb.h
@@ -0,0 +1,1516 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/type.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2ftype_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2ftype_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_enum_reflection.h>
+#include <google/protobuf/unknown_field_set.h>
+#include "google/protobuf/any.pb.h"
+#include "google/protobuf/source_context.pb.h"
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto();
+
+class Type;
+class Field;
+class Enum;
+class EnumValue;
+class Option;
+
+enum Field_Kind {
+ Field_Kind_TYPE_UNKNOWN = 0,
+ Field_Kind_TYPE_DOUBLE = 1,
+ Field_Kind_TYPE_FLOAT = 2,
+ Field_Kind_TYPE_INT64 = 3,
+ Field_Kind_TYPE_UINT64 = 4,
+ Field_Kind_TYPE_INT32 = 5,
+ Field_Kind_TYPE_FIXED64 = 6,
+ Field_Kind_TYPE_FIXED32 = 7,
+ Field_Kind_TYPE_BOOL = 8,
+ Field_Kind_TYPE_STRING = 9,
+ Field_Kind_TYPE_MESSAGE = 11,
+ Field_Kind_TYPE_BYTES = 12,
+ Field_Kind_TYPE_UINT32 = 13,
+ Field_Kind_TYPE_ENUM = 14,
+ Field_Kind_TYPE_SFIXED32 = 15,
+ Field_Kind_TYPE_SFIXED64 = 16,
+ Field_Kind_TYPE_SINT32 = 17,
+ Field_Kind_TYPE_SINT64 = 18,
+ Field_Kind_Field_Kind_INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,
+ Field_Kind_Field_Kind_INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max
+};
+LIBPROTOBUF_EXPORT bool Field_Kind_IsValid(int value);
+const Field_Kind Field_Kind_Kind_MIN = Field_Kind_TYPE_UNKNOWN;
+const Field_Kind Field_Kind_Kind_MAX = Field_Kind_TYPE_SINT64;
+const int Field_Kind_Kind_ARRAYSIZE = Field_Kind_Kind_MAX + 1;
+
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* Field_Kind_descriptor();
+inline const ::std::string& Field_Kind_Name(Field_Kind value) {
+ return ::google::protobuf::internal::NameOfEnum(
+ Field_Kind_descriptor(), value);
+}
+inline bool Field_Kind_Parse(
+ const ::std::string& name, Field_Kind* value) {
+ return ::google::protobuf::internal::ParseNamedEnum<Field_Kind>(
+ Field_Kind_descriptor(), name, value);
+}
+enum Field_Cardinality {
+ Field_Cardinality_CARDINALITY_UNKNOWN = 0,
+ Field_Cardinality_CARDINALITY_OPTIONAL = 1,
+ Field_Cardinality_CARDINALITY_REQUIRED = 2,
+ Field_Cardinality_CARDINALITY_REPEATED = 3,
+ Field_Cardinality_Field_Cardinality_INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,
+ Field_Cardinality_Field_Cardinality_INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max
+};
+LIBPROTOBUF_EXPORT bool Field_Cardinality_IsValid(int value);
+const Field_Cardinality Field_Cardinality_Cardinality_MIN = Field_Cardinality_CARDINALITY_UNKNOWN;
+const Field_Cardinality Field_Cardinality_Cardinality_MAX = Field_Cardinality_CARDINALITY_REPEATED;
+const int Field_Cardinality_Cardinality_ARRAYSIZE = Field_Cardinality_Cardinality_MAX + 1;
+
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* Field_Cardinality_descriptor();
+inline const ::std::string& Field_Cardinality_Name(Field_Cardinality value) {
+ return ::google::protobuf::internal::NameOfEnum(
+ Field_Cardinality_descriptor(), value);
+}
+inline bool Field_Cardinality_Parse(
+ const ::std::string& name, Field_Cardinality* value) {
+ return ::google::protobuf::internal::ParseNamedEnum<Field_Cardinality>(
+ Field_Cardinality_descriptor(), name, value);
+}
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT Type : public ::google::protobuf::Message {
+ public:
+ Type();
+ virtual ~Type();
+
+ Type(const Type& from);
+
+ inline Type& operator=(const Type& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const Type& default_instance();
+
+ void Swap(Type* other);
+
+ // implements Message ----------------------------------------------
+
+ inline Type* New() const { return New(NULL); }
+
+ Type* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const Type& from);
+ void MergeFrom(const Type& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(Type* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional string name = 1;
+ void clear_name();
+ static const int kNameFieldNumber = 1;
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
+
+ // repeated .google.protobuf.Field fields = 2;
+ int fields_size() const;
+ void clear_fields();
+ static const int kFieldsFieldNumber = 2;
+ const ::google::protobuf::Field& fields(int index) const;
+ ::google::protobuf::Field* mutable_fields(int index);
+ ::google::protobuf::Field* add_fields();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >&
+ fields() const;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >*
+ mutable_fields();
+
+ // repeated string oneofs = 3;
+ int oneofs_size() const;
+ void clear_oneofs();
+ static const int kOneofsFieldNumber = 3;
+ const ::std::string& oneofs(int index) const;
+ ::std::string* mutable_oneofs(int index);
+ void set_oneofs(int index, const ::std::string& value);
+ void set_oneofs(int index, const char* value);
+ void set_oneofs(int index, const char* value, size_t size);
+ ::std::string* add_oneofs();
+ void add_oneofs(const ::std::string& value);
+ void add_oneofs(const char* value);
+ void add_oneofs(const char* value, size_t size);
+ const ::google::protobuf::RepeatedPtrField< ::std::string>& oneofs() const;
+ ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_oneofs();
+
+ // repeated .google.protobuf.Option options = 4;
+ int options_size() const;
+ void clear_options();
+ static const int kOptionsFieldNumber = 4;
+ const ::google::protobuf::Option& options(int index) const;
+ ::google::protobuf::Option* mutable_options(int index);
+ ::google::protobuf::Option* add_options();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+ options() const;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+ mutable_options();
+
+ // optional .google.protobuf.SourceContext source_context = 5;
+ bool has_source_context() const;
+ void clear_source_context();
+ static const int kSourceContextFieldNumber = 5;
+ const ::google::protobuf::SourceContext& source_context() const;
+ ::google::protobuf::SourceContext* mutable_source_context();
+ ::google::protobuf::SourceContext* release_source_context();
+ void set_allocated_source_context(::google::protobuf::SourceContext* source_context);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.Type)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::internal::ArenaStringPtr name_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field > fields_;
+ ::google::protobuf::RepeatedPtrField< ::std::string> oneofs_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
+ ::google::protobuf::SourceContext* source_context_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto();
+
+ void InitAsDefaultInstance();
+ static Type* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT Field : public ::google::protobuf::Message {
+ public:
+ Field();
+ virtual ~Field();
+
+ Field(const Field& from);
+
+ inline Field& operator=(const Field& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const Field& default_instance();
+
+ void Swap(Field* other);
+
+ // implements Message ----------------------------------------------
+
+ inline Field* New() const { return New(NULL); }
+
+ Field* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const Field& from);
+ void MergeFrom(const Field& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(Field* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // 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_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);
+ }
+ static const Kind Kind_MIN =
+ Field_Kind_Kind_MIN;
+ static const Kind Kind_MAX =
+ Field_Kind_Kind_MAX;
+ static const int Kind_ARRAYSIZE =
+ Field_Kind_Kind_ARRAYSIZE;
+ static inline const ::google::protobuf::EnumDescriptor*
+ Kind_descriptor() {
+ return Field_Kind_descriptor();
+ }
+ static inline const ::std::string& Kind_Name(Kind value) {
+ return Field_Kind_Name(value);
+ }
+ static inline bool Kind_Parse(const ::std::string& name,
+ Kind* value) {
+ return Field_Kind_Parse(name, value);
+ }
+
+ 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 inline bool Cardinality_IsValid(int value) {
+ return Field_Cardinality_IsValid(value);
+ }
+ static const Cardinality Cardinality_MIN =
+ Field_Cardinality_Cardinality_MIN;
+ static const Cardinality Cardinality_MAX =
+ Field_Cardinality_Cardinality_MAX;
+ static const int Cardinality_ARRAYSIZE =
+ Field_Cardinality_Cardinality_ARRAYSIZE;
+ static inline const ::google::protobuf::EnumDescriptor*
+ Cardinality_descriptor() {
+ return Field_Cardinality_descriptor();
+ }
+ static inline const ::std::string& Cardinality_Name(Cardinality value) {
+ return Field_Cardinality_Name(value);
+ }
+ static inline bool Cardinality_Parse(const ::std::string& name,
+ Cardinality* value) {
+ return Field_Cardinality_Parse(name, value);
+ }
+
+ // accessors -------------------------------------------------------
+
+ // optional .google.protobuf.Field.Kind kind = 1;
+ void clear_kind();
+ static const int kKindFieldNumber = 1;
+ ::google::protobuf::Field_Kind kind() const;
+ void set_kind(::google::protobuf::Field_Kind value);
+
+ // optional .google.protobuf.Field.Cardinality cardinality = 2;
+ void clear_cardinality();
+ static const int kCardinalityFieldNumber = 2;
+ ::google::protobuf::Field_Cardinality cardinality() const;
+ void set_cardinality(::google::protobuf::Field_Cardinality value);
+
+ // optional int32 number = 3;
+ void clear_number();
+ static const int kNumberFieldNumber = 3;
+ ::google::protobuf::int32 number() const;
+ void set_number(::google::protobuf::int32 value);
+
+ // optional string name = 4;
+ void clear_name();
+ static const int kNameFieldNumber = 4;
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
+
+ // optional string type_url = 6;
+ void clear_type_url();
+ static const int kTypeUrlFieldNumber = 6;
+ const ::std::string& type_url() const;
+ void set_type_url(const ::std::string& value);
+ void set_type_url(const char* value);
+ void set_type_url(const char* value, size_t size);
+ ::std::string* mutable_type_url();
+ ::std::string* release_type_url();
+ void set_allocated_type_url(::std::string* type_url);
+
+ // optional int32 oneof_index = 7;
+ void clear_oneof_index();
+ static const int kOneofIndexFieldNumber = 7;
+ ::google::protobuf::int32 oneof_index() const;
+ void set_oneof_index(::google::protobuf::int32 value);
+
+ // optional bool packed = 8;
+ void clear_packed();
+ static const int kPackedFieldNumber = 8;
+ bool packed() const;
+ void set_packed(bool value);
+
+ // repeated .google.protobuf.Option options = 9;
+ int options_size() const;
+ void clear_options();
+ static const int kOptionsFieldNumber = 9;
+ const ::google::protobuf::Option& options(int index) const;
+ ::google::protobuf::Option* mutable_options(int index);
+ ::google::protobuf::Option* add_options();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+ options() const;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+ mutable_options();
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.Field)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ int kind_;
+ int cardinality_;
+ ::google::protobuf::internal::ArenaStringPtr name_;
+ ::google::protobuf::int32 number_;
+ ::google::protobuf::int32 oneof_index_;
+ ::google::protobuf::internal::ArenaStringPtr type_url_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
+ bool packed_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto();
+
+ void InitAsDefaultInstance();
+ static Field* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT Enum : public ::google::protobuf::Message {
+ public:
+ Enum();
+ virtual ~Enum();
+
+ Enum(const Enum& from);
+
+ inline Enum& operator=(const Enum& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const Enum& default_instance();
+
+ void Swap(Enum* other);
+
+ // implements Message ----------------------------------------------
+
+ inline Enum* New() const { return New(NULL); }
+
+ Enum* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const Enum& from);
+ void MergeFrom(const Enum& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(Enum* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional string name = 1;
+ void clear_name();
+ static const int kNameFieldNumber = 1;
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
+
+ // repeated .google.protobuf.EnumValue enumvalue = 2;
+ int enumvalue_size() const;
+ void clear_enumvalue();
+ static const int kEnumvalueFieldNumber = 2;
+ const ::google::protobuf::EnumValue& enumvalue(int index) const;
+ ::google::protobuf::EnumValue* mutable_enumvalue(int index);
+ ::google::protobuf::EnumValue* add_enumvalue();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >&
+ enumvalue() const;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >*
+ mutable_enumvalue();
+
+ // repeated .google.protobuf.Option options = 3;
+ int options_size() const;
+ void clear_options();
+ static const int kOptionsFieldNumber = 3;
+ const ::google::protobuf::Option& options(int index) const;
+ ::google::protobuf::Option* mutable_options(int index);
+ ::google::protobuf::Option* add_options();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+ options() const;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+ mutable_options();
+
+ // optional .google.protobuf.SourceContext source_context = 4;
+ bool has_source_context() const;
+ void clear_source_context();
+ static const int kSourceContextFieldNumber = 4;
+ const ::google::protobuf::SourceContext& source_context() const;
+ ::google::protobuf::SourceContext* mutable_source_context();
+ ::google::protobuf::SourceContext* release_source_context();
+ void set_allocated_source_context(::google::protobuf::SourceContext* source_context);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.Enum)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::internal::ArenaStringPtr name_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue > enumvalue_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
+ ::google::protobuf::SourceContext* source_context_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto();
+
+ void InitAsDefaultInstance();
+ static Enum* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT EnumValue : public ::google::protobuf::Message {
+ public:
+ EnumValue();
+ virtual ~EnumValue();
+
+ EnumValue(const EnumValue& from);
+
+ inline EnumValue& operator=(const EnumValue& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const EnumValue& default_instance();
+
+ void Swap(EnumValue* other);
+
+ // implements Message ----------------------------------------------
+
+ inline EnumValue* New() const { return New(NULL); }
+
+ EnumValue* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const EnumValue& from);
+ void MergeFrom(const EnumValue& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(EnumValue* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional string name = 1;
+ void clear_name();
+ static const int kNameFieldNumber = 1;
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
+
+ // optional int32 number = 2;
+ void clear_number();
+ static const int kNumberFieldNumber = 2;
+ ::google::protobuf::int32 number() const;
+ void set_number(::google::protobuf::int32 value);
+
+ // repeated .google.protobuf.Option options = 3;
+ int options_size() const;
+ void clear_options();
+ static const int kOptionsFieldNumber = 3;
+ const ::google::protobuf::Option& options(int index) const;
+ ::google::protobuf::Option* mutable_options(int index);
+ ::google::protobuf::Option* add_options();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+ options() const;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+ mutable_options();
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.EnumValue)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::internal::ArenaStringPtr name_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
+ ::google::protobuf::int32 number_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto();
+
+ void InitAsDefaultInstance();
+ static EnumValue* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT Option : public ::google::protobuf::Message {
+ public:
+ Option();
+ virtual ~Option();
+
+ Option(const Option& from);
+
+ inline Option& operator=(const Option& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const Option& default_instance();
+
+ void Swap(Option* other);
+
+ // implements Message ----------------------------------------------
+
+ inline Option* New() const { return New(NULL); }
+
+ Option* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const Option& from);
+ void MergeFrom(const Option& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(Option* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional string name = 1;
+ void clear_name();
+ static const int kNameFieldNumber = 1;
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
+
+ // optional .google.protobuf.Any value = 2;
+ bool has_value() const;
+ void clear_value();
+ static const int kValueFieldNumber = 2;
+ const ::google::protobuf::Any& value() const;
+ ::google::protobuf::Any* mutable_value();
+ ::google::protobuf::Any* release_value();
+ void set_allocated_value(::google::protobuf::Any* value);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.Option)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::internal::ArenaStringPtr name_;
+ ::google::protobuf::Any* value_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto();
+
+ void InitAsDefaultInstance();
+ static Option* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// Type
+
+// optional string name = 1;
+inline void Type::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Type::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Type.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Type::set_name(const ::std::string& value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Type.name)
+}
+inline void Type::set_name(const char* value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Type.name)
+}
+inline void Type::set_name(const char* value, size_t size) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.name)
+}
+inline ::std::string* Type::mutable_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Type.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Type::release_name() {
+
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Type::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+
+ } else {
+
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Type.name)
+}
+
+// repeated .google.protobuf.Field fields = 2;
+inline int Type::fields_size() const {
+ return fields_.size();
+}
+inline void Type::clear_fields() {
+ fields_.Clear();
+}
+inline const ::google::protobuf::Field& Type::fields(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Type.fields)
+ return fields_.Get(index);
+}
+inline ::google::protobuf::Field* Type::mutable_fields(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Type.fields)
+ return fields_.Mutable(index);
+}
+inline ::google::protobuf::Field* Type::add_fields() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Type.fields)
+ return fields_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >&
+Type::fields() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Type.fields)
+ return fields_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >*
+Type::mutable_fields() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.fields)
+ return &fields_;
+}
+
+// repeated string oneofs = 3;
+inline int Type::oneofs_size() const {
+ return oneofs_.size();
+}
+inline void Type::clear_oneofs() {
+ oneofs_.Clear();
+}
+inline const ::std::string& Type::oneofs(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Type.oneofs)
+ return oneofs_.Get(index);
+}
+inline ::std::string* Type::mutable_oneofs(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Type.oneofs)
+ return oneofs_.Mutable(index);
+}
+inline void Type::set_oneofs(int index, const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.Type.oneofs)
+ oneofs_.Mutable(index)->assign(value);
+}
+inline void Type::set_oneofs(int index, const char* value) {
+ oneofs_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Type.oneofs)
+}
+inline void Type::set_oneofs(int index, const char* value, size_t size) {
+ oneofs_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.oneofs)
+}
+inline ::std::string* Type::add_oneofs() {
+ return oneofs_.Add();
+}
+inline void Type::add_oneofs(const ::std::string& value) {
+ oneofs_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.Type.oneofs)
+}
+inline void Type::add_oneofs(const char* value) {
+ oneofs_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.Type.oneofs)
+}
+inline void Type::add_oneofs(const char* value, size_t size) {
+ oneofs_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.Type.oneofs)
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+Type::oneofs() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Type.oneofs)
+ return oneofs_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+Type::mutable_oneofs() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.oneofs)
+ return &oneofs_;
+}
+
+// repeated .google.protobuf.Option options = 4;
+inline int Type::options_size() const {
+ return options_.size();
+}
+inline void Type::clear_options() {
+ options_.Clear();
+}
+inline const ::google::protobuf::Option& Type::options(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Type.options)
+ return options_.Get(index);
+}
+inline ::google::protobuf::Option* Type::mutable_options(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Type.options)
+ return options_.Mutable(index);
+}
+inline ::google::protobuf::Option* Type::add_options() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Type.options)
+ return options_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Type::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Type.options)
+ return options_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Type::mutable_options() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.options)
+ return &options_;
+}
+
+// optional .google.protobuf.SourceContext source_context = 5;
+inline bool Type::has_source_context() const {
+ return !_is_default_instance_ && source_context_ != NULL;
+}
+inline void Type::clear_source_context() {
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+ source_context_ = NULL;
+}
+inline const ::google::protobuf::SourceContext& Type::source_context() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Type.source_context)
+ return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
+}
+inline ::google::protobuf::SourceContext* Type::mutable_source_context() {
+
+ if (source_context_ == NULL) {
+ source_context_ = new ::google::protobuf::SourceContext;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Type.source_context)
+ return source_context_;
+}
+inline ::google::protobuf::SourceContext* Type::release_source_context() {
+
+ ::google::protobuf::SourceContext* temp = source_context_;
+ source_context_ = NULL;
+ return temp;
+}
+inline void Type::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
+ delete source_context_;
+ source_context_ = source_context;
+ if (source_context) {
+
+ } else {
+
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Type.source_context)
+}
+
+// -------------------------------------------------------------------
+
+// Field
+
+// optional .google.protobuf.Field.Kind kind = 1;
+inline void Field::clear_kind() {
+ kind_ = 0;
+}
+inline ::google::protobuf::Field_Kind Field::kind() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.kind)
+ return static_cast< ::google::protobuf::Field_Kind >(kind_);
+}
+inline void Field::set_kind(::google::protobuf::Field_Kind value) {
+
+ kind_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Field.kind)
+}
+
+// optional .google.protobuf.Field.Cardinality cardinality = 2;
+inline void Field::clear_cardinality() {
+ cardinality_ = 0;
+}
+inline ::google::protobuf::Field_Cardinality Field::cardinality() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.cardinality)
+ return static_cast< ::google::protobuf::Field_Cardinality >(cardinality_);
+}
+inline void Field::set_cardinality(::google::protobuf::Field_Cardinality value) {
+
+ cardinality_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Field.cardinality)
+}
+
+// optional int32 number = 3;
+inline void Field::clear_number() {
+ number_ = 0;
+}
+inline ::google::protobuf::int32 Field::number() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.number)
+ return number_;
+}
+inline void Field::set_number(::google::protobuf::int32 value) {
+
+ number_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Field.number)
+}
+
+// optional string name = 4;
+inline void Field::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Field::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Field::set_name(const ::std::string& value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Field.name)
+}
+inline void Field::set_name(const char* value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Field.name)
+}
+inline void Field::set_name(const char* value, size_t size) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.name)
+}
+inline ::std::string* Field::mutable_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Field.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Field::release_name() {
+
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Field::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+
+ } else {
+
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.name)
+}
+
+// optional string type_url = 6;
+inline void Field::clear_type_url() {
+ type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Field::type_url() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.type_url)
+ return type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Field::set_type_url(const ::std::string& value) {
+
+ type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Field.type_url)
+}
+inline void Field::set_type_url(const char* value) {
+
+ type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Field.type_url)
+}
+inline void Field::set_type_url(const char* value, size_t size) {
+
+ type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.type_url)
+}
+inline ::std::string* Field::mutable_type_url() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Field.type_url)
+ return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Field::release_type_url() {
+
+ return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Field::set_allocated_type_url(::std::string* type_url) {
+ if (type_url != NULL) {
+
+ } else {
+
+ }
+ type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_url);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.type_url)
+}
+
+// optional int32 oneof_index = 7;
+inline void Field::clear_oneof_index() {
+ oneof_index_ = 0;
+}
+inline ::google::protobuf::int32 Field::oneof_index() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.oneof_index)
+ return oneof_index_;
+}
+inline void Field::set_oneof_index(::google::protobuf::int32 value) {
+
+ oneof_index_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Field.oneof_index)
+}
+
+// optional bool packed = 8;
+inline void Field::clear_packed() {
+ packed_ = false;
+}
+inline bool Field::packed() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.packed)
+ return packed_;
+}
+inline void Field::set_packed(bool value) {
+
+ packed_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Field.packed)
+}
+
+// repeated .google.protobuf.Option options = 9;
+inline int Field::options_size() const {
+ return options_.size();
+}
+inline void Field::clear_options() {
+ options_.Clear();
+}
+inline const ::google::protobuf::Option& Field::options(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Field.options)
+ return options_.Get(index);
+}
+inline ::google::protobuf::Option* Field::mutable_options(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Field.options)
+ return options_.Mutable(index);
+}
+inline ::google::protobuf::Option* Field::add_options() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Field.options)
+ return options_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Field::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Field.options)
+ return options_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Field::mutable_options() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Field.options)
+ return &options_;
+}
+
+// -------------------------------------------------------------------
+
+// Enum
+
+// optional string name = 1;
+inline void Enum::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Enum::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Enum.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Enum::set_name(const ::std::string& value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Enum.name)
+}
+inline void Enum::set_name(const char* value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Enum.name)
+}
+inline void Enum::set_name(const char* value, size_t size) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Enum.name)
+}
+inline ::std::string* Enum::mutable_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Enum::release_name() {
+
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Enum::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+
+ } else {
+
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Enum.name)
+}
+
+// repeated .google.protobuf.EnumValue enumvalue = 2;
+inline int Enum::enumvalue_size() const {
+ return enumvalue_.size();
+}
+inline void Enum::clear_enumvalue() {
+ enumvalue_.Clear();
+}
+inline const ::google::protobuf::EnumValue& Enum::enumvalue(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Enum.enumvalue)
+ return enumvalue_.Get(index);
+}
+inline ::google::protobuf::EnumValue* Enum::mutable_enumvalue(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.enumvalue)
+ return enumvalue_.Mutable(index);
+}
+inline ::google::protobuf::EnumValue* Enum::add_enumvalue() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Enum.enumvalue)
+ return enumvalue_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >&
+Enum::enumvalue() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Enum.enumvalue)
+ return enumvalue_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >*
+Enum::mutable_enumvalue() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Enum.enumvalue)
+ return &enumvalue_;
+}
+
+// repeated .google.protobuf.Option options = 3;
+inline int Enum::options_size() const {
+ return options_.size();
+}
+inline void Enum::clear_options() {
+ options_.Clear();
+}
+inline const ::google::protobuf::Option& Enum::options(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Enum.options)
+ return options_.Get(index);
+}
+inline ::google::protobuf::Option* Enum::mutable_options(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.options)
+ return options_.Mutable(index);
+}
+inline ::google::protobuf::Option* Enum::add_options() {
+ // @@protoc_insertion_point(field_add:google.protobuf.Enum.options)
+ return options_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+Enum::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.Enum.options)
+ return options_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+Enum::mutable_options() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.Enum.options)
+ return &options_;
+}
+
+// optional .google.protobuf.SourceContext source_context = 4;
+inline bool Enum::has_source_context() const {
+ return !_is_default_instance_ && source_context_ != NULL;
+}
+inline void Enum::clear_source_context() {
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
+ source_context_ = NULL;
+}
+inline const ::google::protobuf::SourceContext& Enum::source_context() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Enum.source_context)
+ return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
+}
+inline ::google::protobuf::SourceContext* Enum::mutable_source_context() {
+
+ if (source_context_ == NULL) {
+ source_context_ = new ::google::protobuf::SourceContext;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.source_context)
+ return source_context_;
+}
+inline ::google::protobuf::SourceContext* Enum::release_source_context() {
+
+ ::google::protobuf::SourceContext* temp = source_context_;
+ source_context_ = NULL;
+ return temp;
+}
+inline void Enum::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
+ delete source_context_;
+ source_context_ = source_context;
+ if (source_context) {
+
+ } else {
+
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Enum.source_context)
+}
+
+// -------------------------------------------------------------------
+
+// EnumValue
+
+// optional string name = 1;
+inline void EnumValue::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& EnumValue::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void EnumValue::set_name(const ::std::string& value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.name)
+}
+inline void EnumValue::set_name(const char* value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValue.name)
+}
+inline void EnumValue::set_name(const char* value, size_t size) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValue.name)
+}
+inline ::std::string* EnumValue::mutable_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValue.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* EnumValue::release_name() {
+
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void EnumValue::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+
+ } else {
+
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValue.name)
+}
+
+// optional int32 number = 2;
+inline void EnumValue::clear_number() {
+ number_ = 0;
+}
+inline ::google::protobuf::int32 EnumValue::number() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.number)
+ return number_;
+}
+inline void EnumValue::set_number(::google::protobuf::int32 value) {
+
+ number_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.number)
+}
+
+// repeated .google.protobuf.Option options = 3;
+inline int EnumValue::options_size() const {
+ return options_.size();
+}
+inline void EnumValue::clear_options() {
+ options_.Clear();
+}
+inline const ::google::protobuf::Option& EnumValue::options(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.options)
+ return options_.Get(index);
+}
+inline ::google::protobuf::Option* EnumValue::mutable_options(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValue.options)
+ return options_.Mutable(index);
+}
+inline ::google::protobuf::Option* EnumValue::add_options() {
+ // @@protoc_insertion_point(field_add:google.protobuf.EnumValue.options)
+ return options_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
+EnumValue::options() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumValue.options)
+ return options_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
+EnumValue::mutable_options() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValue.options)
+ return &options_;
+}
+
+// -------------------------------------------------------------------
+
+// Option
+
+// optional string name = 1;
+inline void Option::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Option::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Option.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Option::set_name(const ::std::string& value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.Option.name)
+}
+inline void Option::set_name(const char* value) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.Option.name)
+}
+inline void Option::set_name(const char* value, size_t size) {
+
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.Option.name)
+}
+inline ::std::string* Option::mutable_name() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Option.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Option::release_name() {
+
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Option::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+
+ } else {
+
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Option.name)
+}
+
+// optional .google.protobuf.Any value = 2;
+inline bool Option::has_value() const {
+ return !_is_default_instance_ && value_ != NULL;
+}
+inline void Option::clear_value() {
+ if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_;
+ value_ = NULL;
+}
+inline const ::google::protobuf::Any& Option::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Option.value)
+ return value_ != NULL ? *value_ : *default_instance_->value_;
+}
+inline ::google::protobuf::Any* Option::mutable_value() {
+
+ if (value_ == NULL) {
+ value_ = new ::google::protobuf::Any;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.Option.value)
+ return value_;
+}
+inline ::google::protobuf::Any* Option::release_value() {
+
+ ::google::protobuf::Any* temp = value_;
+ value_ = NULL;
+ return temp;
+}
+inline void Option::set_allocated_value(::google::protobuf::Any* value) {
+ delete value_;
+ value_ = value;
+ if (value) {
+
+ } else {
+
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.Option.value)
+}
+
+#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+#ifndef SWIG
+namespace google {
+namespace protobuf {
+
+template <> struct is_proto_enum< ::google::protobuf::Field_Kind> : ::google::protobuf::internal::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::Field_Kind>() {
+ return ::google::protobuf::Field_Kind_descriptor();
+}
+template <> struct is_proto_enum< ::google::protobuf::Field_Cardinality> : ::google::protobuf::internal::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::Field_Cardinality>() {
+ return ::google::protobuf::Field_Cardinality_descriptor();
+}
+
+} // namespace protobuf
+} // namespace google
+#endif // SWIG
+
+// @@protoc_insertion_point(global_scope)
+
+#endif // PROTOBUF_google_2fprotobuf_2ftype_2eproto__INCLUDED
diff --git a/src/google/protobuf/type.proto b/src/google/protobuf/type.proto
new file mode 100644
index 00000000..ce22d33d
--- /dev/null
+++ b/src/google/protobuf/type.proto
@@ -0,0 +1,198 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+syntax = "proto3";
+
+package google.protobuf;
+
+import "google/protobuf/any.proto";
+import "google/protobuf/source_context.proto";
+
+option java_multiple_files = true;
+option java_outer_classname = "TypeProto";
+option java_package = "com.google.protobuf";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option objc_class_prefix = "GPB";
+
+
+// A light-weight descriptor for a proto message type.
+message Type {
+ // The fully qualified message name.
+ string name = 1;
+
+ // The list of fields.
+ repeated Field fields = 2;
+
+ // The list of oneof definitions.
+ // The list of oneofs declared in this Type
+ repeated string oneofs = 3;
+
+ // The proto options.
+ repeated Option options = 4;
+
+ // The source context.
+ SourceContext source_context = 5;
+}
+
+// Field represents a single field of a message type.
+message Field {
+ // Kind represents a basic field type.
+ enum Kind {
+ // Field type unknown.
+ TYPE_UNKNOWN = 0;
+
+ // Field type double.
+ TYPE_DOUBLE = 1;
+
+ // Field type float.
+ TYPE_FLOAT = 2;
+
+ // Field type int64.
+ TYPE_INT64 = 3;
+
+ // Field type uint64.
+ TYPE_UINT64 = 4;
+
+ // Field type int32.
+ TYPE_INT32 = 5;
+
+ // Field type fixed64.
+ TYPE_FIXED64 = 6;
+
+ // Field type fixed32.
+ TYPE_FIXED32 = 7;
+
+ // Field type bool.
+ TYPE_BOOL = 8;
+
+ // Field type string.
+ TYPE_STRING = 9;
+
+ // Field type message.
+ TYPE_MESSAGE = 11;
+
+ // Field type bytes.
+ TYPE_BYTES = 12;
+
+ // Field type uint32.
+ TYPE_UINT32 = 13;
+
+ // Field type enum.
+ TYPE_ENUM = 14;
+
+ // Field type sfixed32.
+ TYPE_SFIXED32 = 15;
+
+ // Field type sfixed64.
+ TYPE_SFIXED64 = 16;
+
+ // Field type sint32.
+ TYPE_SINT32 = 17;
+
+ // Field type sint64.
+ TYPE_SINT64 = 18;
+ }
+
+ // Cardinality represents whether a field is optional, required, or
+ // repeated.
+ enum Cardinality {
+ // The field cardinality is unknown. Typically an error condition.
+ CARDINALITY_UNKNOWN = 0;
+
+ // For optional fields.
+ CARDINALITY_OPTIONAL = 1;
+
+ // For required fields. Not used for proto3.
+ CARDINALITY_REQUIRED = 2;
+
+ // For repeated fields.
+ CARDINALITY_REPEATED = 3;
+ }
+
+ // The field kind.
+ Kind kind = 1;
+
+ // The field cardinality, i.e. optional/required/repeated.
+ Cardinality cardinality = 2;
+
+ // The proto field number.
+ int32 number = 3;
+
+ // The field name.
+ string name = 4;
+
+ // The type URL (without the scheme) when the type is MESSAGE or ENUM,
+ // such as `type.googleapis.com/google.protobuf.Empty`.
+ string type_url = 6;
+
+ // Index in Type.oneofs. Starts at 1. Zero means no oneof mapping.
+ int32 oneof_index = 7;
+
+ // Whether to use alternative packed wire representation.
+ bool packed = 8;
+
+ // The proto options.
+ repeated Option options = 9;
+}
+
+// Enum type definition.
+message Enum {
+ // Enum type name.
+ string name = 1;
+
+ // Enum value definitions.
+ repeated EnumValue enumvalue = 2;
+
+ // Proto options for the enum type.
+ repeated Option options = 3;
+
+ // The source context.
+ SourceContext source_context = 4;
+}
+
+// Enum value definition.
+message EnumValue {
+ // Enum value name.
+ string name = 1;
+
+ // Enum value number.
+ int32 number = 2;
+
+ // Proto options for the enum value.
+ repeated Option options = 3;
+}
+
+// Proto option attached to messages/fields/enums etc.
+message Option {
+ // Proto option name.
+ string name = 1;
+
+ // Proto option value.
+ Any value = 2;
+}
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index 745f77c5..85fe6153 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -184,6 +184,7 @@ message TestAllTypes {
message NestedTestAllTypes {
optional NestedTestAllTypes child = 1;
optional TestAllTypes payload = 2;
+ repeated NestedTestAllTypes repeated_child = 3;
}
message TestDeprecatedFields {
@@ -202,6 +203,11 @@ enum ForeignEnum {
FOREIGN_BAZ = 6;
}
+message TestReservedFields {
+ reserved 2, 15, 9 to 11;
+ reserved "bar", "baz";
+}
+
message TestAllExtensions {
extensions 1 to max;
}
diff --git a/src/google/protobuf/unittest_drop_unknown_fields.proto b/src/google/protobuf/unittest_drop_unknown_fields.proto
index 66b31acf..8aa3a37b 100644
--- a/src/google/protobuf/unittest_drop_unknown_fields.proto
+++ b/src/google/protobuf/unittest_drop_unknown_fields.proto
@@ -31,6 +31,9 @@
syntax = "proto3";
package unittest_drop_unknown_fields;
+option objc_class_prefix = "DropUnknowns";
+
+option csharp_namespace = "Google.Protobuf.TestProtos";
message Foo {
enum NestedEnum {
@@ -38,8 +41,8 @@ message Foo {
BAR = 1;
BAZ = 2;
}
- optional int32 int32_value = 1;
- optional NestedEnum enum_value = 2;
+ int32 int32_value = 1;
+ NestedEnum enum_value = 2;
}
message FooWithExtraFields {
@@ -49,7 +52,7 @@ message FooWithExtraFields {
BAZ = 2;
QUX = 3;
}
- optional int32 int32_value = 1;
- optional NestedEnum enum_value = 2;
- optional int32 extra_int32_value = 3;
+ int32 int32_value = 1;
+ NestedEnum enum_value = 2;
+ int32 extra_int32_value = 3;
}
diff --git a/src/google/protobuf/unittest_enormous_descriptor.proto b/src/google/protobuf/unittest_enormous_descriptor.proto
index 2250261d..6e65dc18 100644
--- a/src/google/protobuf/unittest_enormous_descriptor.proto
+++ b/src/google/protobuf/unittest_enormous_descriptor.proto
@@ -33,7 +33,8 @@
// Sanjay Ghemawat, Jeff Dean, and others.
//
// A proto file that has an extremely large descriptor. Used to test that
-// descriptors over 64k don't break the string literal length limit in Java.
+// descriptors over 64k don't break language-specific limits in generated code,
+// such as the string literal length limit in Java.
syntax = "proto2";
diff --git a/src/google/protobuf/unittest_import_proto3.proto b/src/google/protobuf/unittest_import_proto3.proto
new file mode 100644
index 00000000..59673eaf
--- /dev/null
+++ b/src/google/protobuf/unittest_import_proto3.proto
@@ -0,0 +1,68 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file which is imported by unittest_proto3.proto to test importing.
+
+syntax = "proto3";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In test_util.h we do
+// "using namespace unittest_import = protobuf_unittest_import".
+package protobuf_unittest_import;
+
+option optimize_for = SPEED;
+option cc_enable_arenas = true;
+
+// Exercise the java_package option.
+option java_package = "com.google.protobuf.test";
+option csharp_namespace = "Google.Protobuf.TestProtos";
+
+// Do not set a java_outer_classname here to verify that Proto2 works without
+// one.
+
+// Test public import
+import public "google/protobuf/unittest_import_public_proto3.proto";
+
+message ImportMessage {
+ int32 d = 1;
+}
+
+enum ImportEnum {
+ IMPORT_ENUM_UNSPECIFIED = 0;
+ IMPORT_FOO = 7;
+ IMPORT_BAR = 8;
+ IMPORT_BAZ = 9;
+}
+
diff --git a/src/google/protobuf/unittest_import_public_proto3.proto b/src/google/protobuf/unittest_import_public_proto3.proto
new file mode 100644
index 00000000..d6f11e28
--- /dev/null
+++ b/src/google/protobuf/unittest_import_public_proto3.proto
@@ -0,0 +1,42 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: liujisi@google.com (Pherl Liu)
+
+syntax = "proto3";
+
+package protobuf_unittest_import;
+
+option java_package = "com.google.protobuf.test";
+option csharp_namespace = "Google.Protobuf.TestProtos";
+
+message PublicImportMessage {
+ int32 e = 1;
+}
diff --git a/src/google/protobuf/unittest_no_arena.proto b/src/google/protobuf/unittest_no_arena.proto
index 1a420838..36fb8656 100644
--- a/src/google/protobuf/unittest_no_arena.proto
+++ b/src/google/protobuf/unittest_no_arena.proto
@@ -113,7 +113,7 @@ message TestAllTypes {
optional protobuf_unittest_import.PublicImportMessage
optional_public_import_message = 26;
- optional NestedMessage optional_lazy_message = 27 [lazy=true];
+ optional NestedMessage optional_message = 27 [lazy=true];
// Repeated
repeated int32 repeated_int32 = 31;
@@ -180,6 +180,7 @@ message TestAllTypes {
NestedMessage oneof_nested_message = 112;
string oneof_string = 113;
bytes oneof_bytes = 114;
+ NestedMessage lazy_oneof_nested_message = 115 [lazy=true];
}
}
diff --git a/src/google/protobuf/unittest_no_field_presence.proto b/src/google/protobuf/unittest_no_field_presence.proto
index e04da0ac..994afff4 100644
--- a/src/google/protobuf/unittest_no_field_presence.proto
+++ b/src/google/protobuf/unittest_no_field_presence.proto
@@ -41,7 +41,7 @@ package proto2_nofieldpresence_unittest;
// forms.
message TestAllTypes {
message NestedMessage {
- optional int32 bb = 1;
+ int32 bb = 1;
}
enum NestedEnum {
@@ -53,36 +53,36 @@ message TestAllTypes {
// Singular
// TODO: remove 'optional' labels as soon as CL 69188077 is LGTM'd to make
// 'optional' optional.
- optional int32 optional_int32 = 1;
- optional int64 optional_int64 = 2;
- optional uint32 optional_uint32 = 3;
- optional uint64 optional_uint64 = 4;
- optional sint32 optional_sint32 = 5;
- optional sint64 optional_sint64 = 6;
- optional fixed32 optional_fixed32 = 7;
- optional fixed64 optional_fixed64 = 8;
- optional sfixed32 optional_sfixed32 = 9;
- optional sfixed64 optional_sfixed64 = 10;
- optional float optional_float = 11;
- optional double optional_double = 12;
- optional bool optional_bool = 13;
- optional string optional_string = 14;
- optional bytes optional_bytes = 15;
-
- optional NestedMessage optional_nested_message = 18;
- optional ForeignMessage optional_foreign_message = 19;
- optional protobuf_unittest.TestAllTypes optional_proto2_message = 20;
-
- optional NestedEnum optional_nested_enum = 21;
- optional ForeignEnum optional_foreign_enum = 22;
+ 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;
+
+ NestedMessage optional_nested_message = 18;
+ ForeignMessage optional_foreign_message = 19;
+ protobuf_unittest.TestAllTypes optional_proto2_message = 20;
+
+ NestedEnum optional_nested_enum = 21;
+ ForeignEnum optional_foreign_enum = 22;
// N.B.: proto2-enum-type fields not allowed, because their default values
// might not be zero.
//optional protobuf_unittest.ForeignEnum optional_proto2_enum = 23;
- optional string optional_string_piece = 24 [ctype=STRING_PIECE];
- optional string optional_cord = 25 [ctype=CORD];
+ string optional_string_piece = 24 [ctype=STRING_PIECE];
+ string optional_cord = 25 [ctype=CORD];
- optional NestedMessage optional_lazy_message = 30 [lazy=true];
+ NestedMessage optional_lazy_message = 30 [lazy=true];
// Repeated
repeated int32 repeated_int32 = 31;
@@ -122,13 +122,13 @@ message TestAllTypes {
}
message TestProto2Required {
- optional protobuf_unittest.TestRequired proto2 = 1;
+ protobuf_unittest.TestRequired proto2 = 1;
}
// Define these after TestAllTypes to make sure the compiler can handle
// that.
message ForeignMessage {
- optional int32 c = 1;
+ int32 c = 1;
}
enum ForeignEnum {
diff --git a/src/google/protobuf/unittest_preserve_unknown_enum.proto b/src/google/protobuf/unittest_preserve_unknown_enum.proto
index ba050d70..2f91332c 100644
--- a/src/google/protobuf/unittest_preserve_unknown_enum.proto
+++ b/src/google/protobuf/unittest_preserve_unknown_enum.proto
@@ -30,7 +30,10 @@
syntax = "proto3";
-package proto2_preserve_unknown_enum_unittest;
+package proto3_preserve_unknown_enum_unittest;
+option objc_class_prefix = "UnknownEnums";
+
+option csharp_namespace = "Google.Protobuf.TestProtos";
enum MyEnum {
FOO = 0;
@@ -46,21 +49,23 @@ enum MyEnumPlusExtra {
}
message MyMessage {
- optional MyEnum e = 1;
+ MyEnum e = 1;
repeated MyEnum repeated_e = 2;
repeated MyEnum repeated_packed_e = 3 [packed=true];
+ repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4; // not packed
oneof o {
- MyEnum oneof_e_1 = 4;
- MyEnum oneof_e_2 = 5;
+ MyEnum oneof_e_1 = 5;
+ MyEnum oneof_e_2 = 6;
}
}
message MyMessagePlusExtra {
- optional MyEnumPlusExtra e = 1;
+ MyEnumPlusExtra e = 1;
repeated MyEnumPlusExtra repeated_e = 2;
repeated MyEnumPlusExtra repeated_packed_e = 3 [packed=true];
+ repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4 [packed=true];
oneof o {
- MyEnumPlusExtra oneof_e_1 = 4;
- MyEnumPlusExtra oneof_e_2 = 5;
+ MyEnumPlusExtra oneof_e_1 = 5;
+ MyEnumPlusExtra oneof_e_2 = 6;
}
}
diff --git a/src/google/protobuf/unittest_preserve_unknown_enum2.proto b/src/google/protobuf/unittest_preserve_unknown_enum2.proto
new file mode 100644
index 00000000..adf42968
--- /dev/null
+++ b/src/google/protobuf/unittest_preserve_unknown_enum2.proto
@@ -0,0 +1,50 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package proto2_preserve_unknown_enum_unittest;
+
+enum MyEnum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+}
+
+message MyMessage {
+ optional MyEnum e = 1;
+ repeated MyEnum repeated_e = 2;
+ repeated MyEnum repeated_packed_e = 3 [packed=true];
+ repeated MyEnum repeated_packed_unexpected_e = 4; // not packed
+ oneof o {
+ MyEnum oneof_e_1 = 5;
+ MyEnum oneof_e_2 = 6;
+ }
+}
diff --git a/src/google/protobuf/unittest_proto3.proto b/src/google/protobuf/unittest_proto3.proto
new file mode 100644
index 00000000..f59d2178
--- /dev/null
+++ b/src/google/protobuf/unittest_proto3.proto
@@ -0,0 +1,388 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file we will use for unit testing.
+
+syntax = "proto3";
+
+// Some generic_services option(s) added automatically.
+// See: http://go/proto2-generic-services-default
+option cc_generic_services = true; // auto-added
+option java_generic_services = true; // auto-added
+option py_generic_services = true; // auto-added
+option cc_enable_arenas = true;
+option csharp_namespace = "Google.Protobuf.TestProtos";
+
+import "google/protobuf/unittest_import_proto3.proto";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In test_util.h we do "using namespace unittest = protobuf_unittest".
+package protobuf_unittest;
+
+// Protos optimized for SPEED use a strict superset of the generated code
+// of equivalent ones optimized for CODE_SIZE, so we should optimize all our
+// tests for speed unless explicitly testing code size optimization.
+option optimize_for = SPEED;
+
+option java_outer_classname = "UnittestProto";
+
+// 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 {
+ NESTED_ENUM_UNSPECIFIED = 0;
+ FOO = 1;
+ BAR = 2;
+ BAZ = 3;
+ NEG = -1; // Intentionally negative.
+ }
+
+ // Singular
+ int32 single_int32 = 1;
+ int64 single_int64 = 2;
+ uint32 single_uint32 = 3;
+ uint64 single_uint64 = 4;
+ sint32 single_sint32 = 5;
+ sint64 single_sint64 = 6;
+ fixed32 single_fixed32 = 7;
+ fixed64 single_fixed64 = 8;
+ sfixed32 single_sfixed32 = 9;
+ sfixed64 single_sfixed64 = 10;
+ float single_float = 11;
+ double single_double = 12;
+ bool single_bool = 13;
+ string single_string = 14;
+ bytes single_bytes = 15;
+
+ NestedMessage single_nested_message = 18;
+ ForeignMessage single_foreign_message = 19;
+ protobuf_unittest_import.ImportMessage single_import_message = 20;
+
+ NestedEnum single_nested_enum = 21;
+ ForeignEnum single_foreign_enum = 22;
+ protobuf_unittest_import.ImportEnum single_import_enum = 23;
+
+ // Defined in unittest_import_public.proto
+ protobuf_unittest_import.PublicImportMessage
+ single_public_import_message = 26;
+
+ // 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;
+
+ 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;
+ repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53;
+ // Defined in unittest_import_public.proto
+ repeated protobuf_unittest_import.PublicImportMessage
+ repeated_public_import_message = 54;
+
+ // For oneof test
+ oneof oneof_field {
+ uint32 oneof_uint32 = 111;
+ NestedMessage oneof_nested_message = 112;
+ string oneof_string = 113;
+ bytes oneof_bytes = 114;
+ }
+}
+
+// This proto includes a recusively nested message.
+message NestedTestAllTypes {
+ NestedTestAllTypes child = 1;
+ TestAllTypes payload = 2;
+ repeated NestedTestAllTypes repeated_child = 3;
+}
+
+message TestDeprecatedFields {
+ int32 deprecated_int32 = 1 [deprecated=true];
+}
+
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+ int32 c = 1;
+}
+
+enum ForeignEnum {
+ FOREIGN_UNSPECIFIED = 0;
+ FOREIGN_FOO = 4;
+ FOREIGN_BAR = 5;
+ FOREIGN_BAZ = 6;
+}
+
+message TestReservedFields {
+ reserved 2, 15, 9 to 11;
+ reserved "bar", "baz";
+}
+
+
+// Test that we can use NestedMessage from outside TestAllTypes.
+message TestForeignNested {
+ TestAllTypes.NestedMessage foreign_nested = 1;
+}
+
+// Test that really large tag numbers don't break anything.
+message TestReallyLargeTagNumber {
+ // The largest possible tag number is 2^28 - 1, since the wire format uses
+ // three bits to communicate wire type.
+ int32 a = 1;
+ int32 bb = 268435455;
+}
+
+message TestRecursiveMessage {
+ TestRecursiveMessage a = 1;
+ int32 i = 2;
+}
+
+// Test that mutual recursion works.
+message TestMutualRecursionA {
+ TestMutualRecursionB bb = 1;
+}
+
+message TestMutualRecursionB {
+ TestMutualRecursionA a = 1;
+ int32 optional_int32 = 2;
+}
+
+
+// Test an enum that has multiple values with the same number.
+enum TestEnumWithDupValue {
+ TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED = 0;
+ option allow_alias = true;
+
+ FOO1 = 1;
+ BAR1 = 2;
+ BAZ = 3;
+ FOO2 = 1;
+ BAR2 = 2;
+}
+
+// Test an enum with large, unordered values.
+enum TestSparseEnum {
+ TEST_SPARSE_ENUM_UNSPECIFIED = 0;
+ SPARSE_A = 123;
+ SPARSE_B = 62374;
+ SPARSE_C = 12589234;
+ SPARSE_D = -15;
+ SPARSE_E = -53452;
+ // In proto3, value 0 must be the first one specified
+ // SPARSE_F = 0;
+ SPARSE_G = 2;
+}
+
+// Test message with CamelCase field names. This violates Protocol Buffer
+// standard style.
+message TestCamelCaseFieldNames {
+ int32 PrimitiveField = 1;
+ string StringField = 2;
+ ForeignEnum EnumField = 3;
+ ForeignMessage MessageField = 4;
+
+ repeated int32 RepeatedPrimitiveField = 7;
+ repeated string RepeatedStringField = 8;
+ repeated ForeignEnum RepeatedEnumField = 9;
+ repeated ForeignMessage RepeatedMessageField = 10;
+}
+
+
+// We list fields out of order, to ensure that we're using field number and not
+// field index to determine serialization order.
+message TestFieldOrderings {
+ string my_string = 11;
+ int64 my_int = 1;
+ float my_float = 101;
+ message NestedMessage {
+ int64 oo = 2;
+ // 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;
+ }
+
+ NestedMessage single_nested_message = 200;
+}
+
+message SparseEnumMessage {
+ TestSparseEnum sparse_enum = 1;
+}
+
+// Test String and Bytes: string is for valid UTF-8 strings
+message OneString {
+ string data = 1;
+}
+
+message MoreString {
+ repeated string data = 1;
+}
+
+message OneBytes {
+ bytes data = 1;
+}
+
+message MoreBytes {
+ bytes data = 1;
+}
+
+// Test int32, uint32, int64, uint64, and bool are all compatible
+message Int32Message {
+ int32 data = 1;
+}
+
+message Uint32Message {
+ uint32 data = 1;
+}
+
+message Int64Message {
+ int64 data = 1;
+}
+
+message Uint64Message {
+ uint64 data = 1;
+}
+
+message BoolMessage {
+ bool data = 1;
+}
+
+// Test oneofs.
+message TestOneof {
+ oneof foo {
+ int32 foo_int = 1;
+ string foo_string = 2;
+ TestAllTypes foo_message = 3;
+ }
+}
+
+// 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];
+}
+
+// A message with the same fields as TestPackedTypes, but without packing. Used
+// to test packed <-> unpacked wire compatibility.
+message TestUnpackedTypes {
+ repeated int32 unpacked_int32 = 90 [packed = false];
+ repeated int64 unpacked_int64 = 91 [packed = false];
+ repeated uint32 unpacked_uint32 = 92 [packed = false];
+ repeated uint64 unpacked_uint64 = 93 [packed = false];
+ repeated sint32 unpacked_sint32 = 94 [packed = false];
+ repeated sint64 unpacked_sint64 = 95 [packed = false];
+ repeated fixed32 unpacked_fixed32 = 96 [packed = false];
+ repeated fixed64 unpacked_fixed64 = 97 [packed = false];
+ repeated sfixed32 unpacked_sfixed32 = 98 [packed = false];
+ repeated sfixed64 unpacked_sfixed64 = 99 [packed = false];
+ repeated float unpacked_float = 100 [packed = false];
+ repeated double unpacked_double = 101 [packed = false];
+ repeated bool unpacked_bool = 102 [packed = false];
+ repeated ForeignEnum unpacked_enum = 103 [packed = false];
+}
+
+message TestRepeatedScalarDifferentTagSizes {
+ // Parsing repeated fixed size values used to fail. This message needs to be
+ // used in order to get a tag of the right size; all of the repeated fields
+ // in TestAllTypes didn't trigger the check.
+ repeated fixed32 repeated_fixed32 = 12;
+ // Check for a varint type, just for good measure.
+ repeated int32 repeated_int32 = 13;
+
+ // These have two-byte tags.
+ repeated fixed64 repeated_fixed64 = 2046;
+ repeated int64 repeated_int64 = 2047;
+
+ // Three byte tags.
+ repeated float repeated_float = 262142;
+ repeated uint64 repeated_uint64 = 262143;
+}
+
+message TestCommentInjectionMessage {
+ // */ <- This should not close the generated doc comment
+ string a = 1;
+}
+
+
+// Test that RPC services work.
+message FooRequest {}
+message FooResponse {}
+
+message FooClientMessage {}
+message FooServerMessage{}
+
+service TestService {
+ rpc Foo(FooRequest) returns (FooResponse);
+ rpc Bar(BarRequest) returns (BarResponse);
+}
+
+
+message BarRequest {}
+message BarResponse {}
+
diff --git a/src/google/protobuf/unittest_proto3_arena.proto b/src/google/protobuf/unittest_proto3_arena.proto
index 53f23d87..b835a6ba 100644
--- a/src/google/protobuf/unittest_proto3_arena.proto
+++ b/src/google/protobuf/unittest_proto3_arena.proto
@@ -43,52 +43,59 @@ message TestAllTypes {
// 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.
- optional int32 bb = 1;
+ int32 bb = 1;
}
enum NestedEnum {
- FOO = 0;
- BAR = 1;
- BAZ = 2;
+ ZERO = 0;
+ FOO = 1;
+ BAR = 2;
+ BAZ = 3;
NEG = -1; // Intentionally negative.
}
// Singular
- optional int32 optional_int32 = 1;
- optional int64 optional_int64 = 2;
- optional uint32 optional_uint32 = 3;
- optional uint64 optional_uint64 = 4;
- optional sint32 optional_sint32 = 5;
- optional sint64 optional_sint64 = 6;
- optional fixed32 optional_fixed32 = 7;
- optional fixed64 optional_fixed64 = 8;
- optional sfixed32 optional_sfixed32 = 9;
- optional sfixed64 optional_sfixed64 = 10;
- optional float optional_float = 11;
- optional double optional_double = 12;
- optional bool optional_bool = 13;
- optional string optional_string = 14;
- optional bytes optional_bytes = 15;
-
- optional group OptionalGroup = 16 {
- optional int32 a = 17;
- }
-
- optional NestedMessage optional_nested_message = 18;
- optional ForeignMessage optional_foreign_message = 19;
- optional protobuf_unittest_import.ImportMessage optional_import_message = 20;
-
- optional NestedEnum optional_nested_enum = 21;
- optional ForeignEnum optional_foreign_enum = 22;
-
- optional string optional_string_piece = 24 [ctype=STRING_PIECE];
- optional string optional_cord = 25 [ctype=CORD];
+ 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
- optional protobuf_unittest_import.PublicImportMessage
+ protobuf_unittest_import.PublicImportMessage
optional_public_import_message = 26;
- optional NestedMessage optional_lazy_message = 27 [lazy=true];
+ NestedMessage optional_lazy_message = 27 [lazy=true];
// Repeated
repeated int32 repeated_int32 = 31;
@@ -107,9 +114,10 @@ message TestAllTypes {
repeated string repeated_string = 44;
repeated bytes repeated_bytes = 45;
- repeated group RepeatedGroup = 46 {
- optional int32 a = 47;
- }
+ // 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;
@@ -118,6 +126,11 @@ message TestAllTypes {
repeated NestedEnum repeated_nested_enum = 51;
repeated ForeignEnum repeated_foreign_enum = 52;
+ // Omitted (compared to unittest.proto) because proto2 enums are not allowed
+ // inside proto2 messages.
+ //
+ // repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53;
+
repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
repeated string repeated_cord = 55 [ctype=CORD];
@@ -131,14 +144,63 @@ message TestAllTypes {
}
}
+// Test messages for packed fields
+
+message TestPackedTypes {
+ repeated int32 packed_int32 = 90 [packed = true];
+ repeated int64 packed_int64 = 91 [packed = true];
+ repeated uint32 packed_uint32 = 92 [packed = true];
+ repeated uint64 packed_uint64 = 93 [packed = true];
+ repeated sint32 packed_sint32 = 94 [packed = true];
+ repeated sint64 packed_sint64 = 95 [packed = true];
+ repeated fixed32 packed_fixed32 = 96 [packed = true];
+ repeated fixed64 packed_fixed64 = 97 [packed = true];
+ repeated sfixed32 packed_sfixed32 = 98 [packed = true];
+ repeated sfixed64 packed_sfixed64 = 99 [packed = true];
+ repeated float packed_float = 100 [packed = true];
+ repeated double packed_double = 101 [packed = true];
+ repeated bool packed_bool = 102 [packed = true];
+ repeated ForeignEnum packed_enum = 103 [packed = true];
+}
+
+// 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 {
- optional int32 c = 1;
+ int32 c = 1;
}
enum ForeignEnum {
- FOREIGN_FOO = 0;
- FOREIGN_BAR = 1;
- FOREIGN_BAZ = 2;
+ FOREIGN_ZERO = 0;
+ FOREIGN_FOO = 4;
+ FOREIGN_BAR = 5;
+ FOREIGN_BAZ = 6;
}
+
+// TestEmptyMessage is used to test behavior of unknown fields.
+message TestEmptyMessage {
+}
+
diff --git a/src/google/protobuf/unittest_well_known_types.proto b/src/google/protobuf/unittest_well_known_types.proto
new file mode 100644
index 00000000..2cb7775c
--- /dev/null
+++ b/src/google/protobuf/unittest_well_known_types.proto
@@ -0,0 +1,112 @@
+syntax = "proto3";
+
+package protobuf_unittest;
+
+option csharp_namespace = "Google.Protobuf.TestProtos";
+option java_multiple_files = true;
+option java_package = "com.google.protobuf.test";
+
+import "google/protobuf/any.proto";
+import "google/protobuf/api.proto";
+import "google/protobuf/duration.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/field_mask.proto";
+import "google/protobuf/source_context.proto";
+import "google/protobuf/struct.proto";
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/type.proto";
+import "google/protobuf/wrappers.proto";
+
+// Test that we can include all well-known types.
+// Each wrapper type is included separately, as languages
+// map handle different wrappers in different ways.
+message TestWellKnownTypes {
+ google.protobuf.Any any_field = 1;
+ google.protobuf.Api api_field = 2;
+ google.protobuf.Duration duration_field = 3;
+ google.protobuf.Empty empty_field = 4;
+ google.protobuf.FieldMask field_mask_field = 5;
+ google.protobuf.SourceContext source_context_field = 6;
+ google.protobuf.Struct struct_field = 7;
+ google.protobuf.Timestamp timestamp_field = 8;
+ google.protobuf.Type type_field = 9;
+ google.protobuf.DoubleValue double_field = 10;
+ google.protobuf.FloatValue float_field = 11;
+ google.protobuf.Int64Value int64_field = 12;
+ google.protobuf.UInt64Value uint64_field = 13;
+ google.protobuf.Int32Value int32_field = 14;
+ google.protobuf.UInt32Value uint32_field = 15;
+ google.protobuf.BoolValue bool_field = 16;
+ google.protobuf.StringValue string_field = 17;
+ google.protobuf.BytesValue bytes_field = 18;
+}
+
+// A repeated field for each well-known type.
+message RepeatedWellKnownTypes {
+ repeated google.protobuf.Any any_field = 1;
+ repeated google.protobuf.Api api_field = 2;
+ repeated google.protobuf.Duration duration_field = 3;
+ repeated google.protobuf.Empty empty_field = 4;
+ repeated google.protobuf.FieldMask field_mask_field = 5;
+ repeated google.protobuf.SourceContext source_context_field = 6;
+ repeated google.protobuf.Struct struct_field = 7;
+ repeated google.protobuf.Timestamp timestamp_field = 8;
+ repeated google.protobuf.Type type_field = 9;
+ // These don't actually make a lot of sense, but they're not prohibited...
+ repeated google.protobuf.DoubleValue double_field = 10;
+ repeated google.protobuf.FloatValue float_field = 11;
+ repeated google.protobuf.Int64Value int64_field = 12;
+ repeated google.protobuf.UInt64Value uint64_field = 13;
+ repeated google.protobuf.Int32Value int32_field = 14;
+ repeated google.protobuf.UInt32Value uint32_field = 15;
+ repeated google.protobuf.BoolValue bool_field = 16;
+ repeated google.protobuf.StringValue string_field = 17;
+ repeated google.protobuf.BytesValue bytes_field = 18;
+}
+
+message OneofWellKnownTypes {
+ oneof oneof_field {
+ google.protobuf.Any any_field = 1;
+ google.protobuf.Api api_field = 2;
+ google.protobuf.Duration duration_field = 3;
+ google.protobuf.Empty empty_field = 4;
+ google.protobuf.FieldMask field_mask_field = 5;
+ google.protobuf.SourceContext source_context_field = 6;
+ google.protobuf.Struct struct_field = 7;
+ google.protobuf.Timestamp timestamp_field = 8;
+ google.protobuf.Type type_field = 9;
+ google.protobuf.DoubleValue double_field = 10;
+ google.protobuf.FloatValue float_field = 11;
+ google.protobuf.Int64Value int64_field = 12;
+ google.protobuf.UInt64Value uint64_field = 13;
+ google.protobuf.Int32Value int32_field = 14;
+ google.protobuf.UInt32Value uint32_field = 15;
+ google.protobuf.BoolValue bool_field = 16;
+ google.protobuf.StringValue string_field = 17;
+ google.protobuf.BytesValue bytes_field = 18;
+ }
+}
+
+// A map field for each well-known type. We only
+// need to worry about the value part of the map being the
+// well-known types, as messages can't be map keys.
+message MapWellKnownTypes {
+ map<int32,google.protobuf.Any> any_field = 1;
+ map<int32,google.protobuf.Api> api_field = 2;
+ map<int32,google.protobuf.Duration> duration_field = 3;
+ map<int32,google.protobuf.Empty> empty_field = 4;
+ map<int32,google.protobuf.FieldMask> field_mask_field = 5;
+ map<int32,google.protobuf.SourceContext> source_context_field = 6;
+ map<int32,google.protobuf.Struct> struct_field = 7;
+ map<int32,google.protobuf.Timestamp> timestamp_field = 8;
+ map<int32,google.protobuf.Type> type_field = 9;
+ map<int32,google.protobuf.DoubleValue> double_field = 10;
+ map<int32,google.protobuf.FloatValue> float_field = 11;
+ map<int32,google.protobuf.Int64Value> int64_field = 12;
+ map<int32,google.protobuf.UInt64Value> uint64_field = 13;
+ map<int32,google.protobuf.Int32Value> int32_field = 14;
+ map<int32,google.protobuf.UInt32Value> uint32_field = 15;
+ map<int32,google.protobuf.BoolValue> bool_field = 16;
+ map<int32,google.protobuf.StringValue> string_field = 17;
+ map<int32,google.protobuf.BytesValue> bytes_field = 18;
+}
diff --git a/src/google/protobuf/unknown_enum_impl.h b/src/google/protobuf/unknown_enum_impl.h
index fb5380aa..39c10cbc 100644
--- a/src/google/protobuf/unknown_enum_impl.h
+++ b/src/google/protobuf/unknown_enum_impl.h
@@ -99,6 +99,29 @@ bool GetRepeatedEnumUnknowns_Template(
}
// NOTE: You should not call these functions directly. Instead use
+// CLEAR_UNKNOWN_ENUM(), defined in the public header. The macro-versions
+// operate in a type-safe manner and behave appropriately for the proto
+// version of the message, whereas these versions assume a specific proto
+// version and allow the caller to pass in any arbitrary integer value as a
+// field number.
+//
+// Clears the unknown entries of the given field of the message.
+void ClearUnknownEnum(Message* message, int32 field_number);
+// In proto1, clears the field if the value is out of range.
+// TODO(karner): Delete this or make it proto2-only once the migration
+// to proto2 is complete.
+void ClearUnknownEnumProto1(Message* message, int32 field_number);
+template <typename T>
+void ClearUnknownEnum_Template(T* message, int32 field_number) {
+ if (internal::is_base_of<bridge::internal::Proto1CompatibleMessage, T>::value ||
+ !internal::is_base_of<ProtocolMessage, T>::value) {
+ ClearUnknownEnum(message, field_number);
+ } else {
+ ClearUnknownEnumProto1(message, field_number);
+ }
+}
+
+// NOTE: You should not call these functions directly. Instead use
// SET_UNKNOWN_ENUM(), defined in the public header. The macro-versions
// operate in a type-safe manner and behave appropriately for the proto
// version of the message, whereas these versions assume a specific proto
diff --git a/src/google/protobuf/unknown_enum_test.proto b/src/google/protobuf/unknown_enum_test.proto
index caafadcd..0ea1ede3 100644
--- a/src/google/protobuf/unknown_enum_test.proto
+++ b/src/google/protobuf/unknown_enum_test.proto
@@ -36,7 +36,6 @@ syntax = "proto2";
package google.protobuf.util;
-
message DownRevision {
enum Enum {
DEFAULT_VALUE = 2;
diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
index e15280c8..93f0f206 100644
--- a/src/google/protobuf/unknown_field_set.cc
+++ b/src/google/protobuf/unknown_field_set.cc
@@ -50,8 +50,13 @@ namespace {
// instantiate the UnknownFieldSet dynamically only when required.
UnknownFieldSet* default_unknown_field_set_instance_ = NULL;
+void DeleteDefaultUnknownFieldSet() {
+ delete default_unknown_field_set_instance_;
+}
+
void InitDefaultUnknownFieldSet() {
default_unknown_field_set_instance_ = new UnknownFieldSet();
+ internal::OnShutdown(&DeleteDefaultUnknownFieldSet);
}
GOOGLE_PROTOBUF_DECLARE_ONCE(default_unknown_field_set_once_init_);
@@ -93,7 +98,7 @@ void UnknownFieldSet::InternalMergeFrom(const UnknownFieldSet& other) {
fields_ = new vector<UnknownField>();
for (int i = 0; i < other_field_count; i++) {
fields_->push_back((*other.fields_)[i]);
- fields_->back().DeepCopy();
+ fields_->back().DeepCopy((*other.fields_)[i]);
}
}
}
@@ -104,7 +109,7 @@ void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
if (fields_ == NULL) fields_ = new vector<UnknownField>();
for (int i = 0; i < other_field_count; i++) {
fields_->push_back((*other.fields_)[i]);
- fields_->back().DeepCopy();
+ fields_->back().DeepCopy((*other.fields_)[i]);
}
}
}
@@ -202,7 +207,7 @@ UnknownFieldSet* UnknownFieldSet::AddGroup(int number) {
void UnknownFieldSet::AddField(const UnknownField& field) {
if (fields_ == NULL) fields_ = new vector<UnknownField>();
fields_->push_back(field);
- fields_->back().DeepCopy();
+ fields_->back().DeepCopy(field);
}
void UnknownFieldSet::DeleteSubrange(int start, int num) {
@@ -303,7 +308,7 @@ void UnknownField::Reset() {
}
}
-void UnknownField::DeepCopy() {
+void UnknownField::DeepCopy(const UnknownField& other) {
switch (type()) {
case UnknownField::TYPE_LENGTH_DELIMITED:
length_delimited_.string_value_ = new string(
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index e8c0a13c..6781cd0f 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -216,19 +216,18 @@ class LIBPROTOBUF_EXPORT UnknownField {
void Reset();
// Make a deep copy of any pointers in this UnknownField.
- void DeepCopy();
+ void DeepCopy(const UnknownField& other);
// Set the wire type of this UnknownField. Should only be used when this
// UnknownField is being created.
inline void SetType(Type type);
- uint32 number_;
- uint32 type_;
-
union LengthDelimited {
string* string_value_;
};
+ uint32 number_;
+ uint32 type_;
union {
uint64 varint_;
uint32 fixed32_;
diff --git a/src/google/protobuf/util/field_comparator.cc b/src/google/protobuf/util/field_comparator.cc
new file mode 100644
index 00000000..9f613265
--- /dev/null
+++ b/src/google/protobuf/util/field_comparator.cc
@@ -0,0 +1,188 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: ksroka@google.com (Krzysztof Sroka)
+
+#include <google/protobuf/util/field_comparator.h>
+
+#include <string>
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/mathlimits.h>
+#include <google/protobuf/stubs/mathutil.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+FieldComparator::FieldComparator() {}
+FieldComparator::~FieldComparator() {}
+
+DefaultFieldComparator::DefaultFieldComparator()
+ : float_comparison_(EXACT),
+ treat_nan_as_equal_(false),
+ has_default_tolerance_(false) {
+}
+
+DefaultFieldComparator::~DefaultFieldComparator() {}
+
+FieldComparator::ComparisonResult DefaultFieldComparator::Compare(
+ const google::protobuf::Message& message_1,
+ const google::protobuf::Message& message_2,
+ const google::protobuf::FieldDescriptor* field,
+ int index_1, int index_2,
+ const google::protobuf::util::FieldContext* field_context) {
+ const Reflection* reflection_1 = message_1.GetReflection();
+ const Reflection* reflection_2 = message_2.GetReflection();
+
+ switch (field->cpp_type()) {
+#define COMPARE_FIELD(METHOD) \
+ if (field->is_repeated()) { \
+ return ResultFromBoolean(Compare##METHOD( \
+ *field, \
+ reflection_1->GetRepeated##METHOD(message_1, field, index_1), \
+ reflection_2->GetRepeated##METHOD(message_2, field, index_2))); \
+ } else { \
+ return ResultFromBoolean(Compare##METHOD( \
+ *field, \
+ reflection_1->Get##METHOD(message_1, field), \
+ reflection_2->Get##METHOD(message_2, field))); \
+ } \
+ break; // Make sure no fall-through is introduced.
+
+ case FieldDescriptor::CPPTYPE_BOOL:
+ COMPARE_FIELD(Bool);
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ COMPARE_FIELD(Double);
+ case FieldDescriptor::CPPTYPE_ENUM:
+ COMPARE_FIELD(Enum);
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ COMPARE_FIELD(Float);
+ case FieldDescriptor::CPPTYPE_INT32:
+ COMPARE_FIELD(Int32);
+ case FieldDescriptor::CPPTYPE_INT64:
+ COMPARE_FIELD(Int64);
+ case FieldDescriptor::CPPTYPE_STRING:
+ COMPARE_FIELD(String);
+ case FieldDescriptor::CPPTYPE_UINT32:
+ COMPARE_FIELD(UInt32);
+ case FieldDescriptor::CPPTYPE_UINT64:
+ COMPARE_FIELD(UInt64);
+
+#undef COMPARE_FIELD
+
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return RECURSE;
+
+ default:
+ GOOGLE_LOG(FATAL) << "No comparison code for field " << field->full_name()
+ << " of CppType = " << field->cpp_type();
+ return DIFFERENT;
+ }
+}
+
+void DefaultFieldComparator::SetDefaultFractionAndMargin(double fraction,
+ double margin) {
+ default_tolerance_ = Tolerance(fraction, margin);
+ has_default_tolerance_ = true;
+}
+
+void DefaultFieldComparator::SetFractionAndMargin(const FieldDescriptor* field,
+ double fraction,
+ double margin) {
+ GOOGLE_CHECK(FieldDescriptor::CPPTYPE_FLOAT == field->cpp_type() ||
+ FieldDescriptor::CPPTYPE_DOUBLE == field->cpp_type())
+ << "Field has to be float or double type. Field name is: "
+ << field->full_name();
+ map_tolerance_[field] = Tolerance(fraction, margin);
+}
+
+bool DefaultFieldComparator::CompareDouble(const FieldDescriptor& field,
+ double value_1, double value_2) {
+ return CompareDoubleOrFloat(field, value_1, value_2);
+}
+
+bool DefaultFieldComparator::CompareEnum(const FieldDescriptor& field,
+ const EnumValueDescriptor* value_1,
+ const EnumValueDescriptor* value_2) {
+ return value_1->number() == value_2->number();
+}
+
+bool DefaultFieldComparator::CompareFloat(const FieldDescriptor& field,
+ float value_1, float value_2) {
+ return CompareDoubleOrFloat(field, value_1, value_2);
+}
+
+template<typename T>
+bool DefaultFieldComparator::CompareDoubleOrFloat(const FieldDescriptor& field,
+ T value_1, T value_2) {
+ if (value_1 == value_2) {
+ // Covers +inf and -inf (which are not within margin or fraction of
+ // themselves), and is a shortcut for finite values.
+ return true;
+ } else if (float_comparison_ == EXACT) {
+ if (treat_nan_as_equal_ &&
+ MathLimits<T>::IsNaN(value_1) && MathLimits<T>::IsNaN(value_2)) {
+ return true;
+ }
+ return false;
+ } else {
+ if (treat_nan_as_equal_ &&
+ MathLimits<T>::IsNaN(value_1) && MathLimits<T>::IsNaN(value_2)) {
+ return true;
+ }
+ // float_comparison_ == APPROXIMATE covers two use cases.
+ Tolerance* tolerance = FindOrNull(map_tolerance_, &field);
+ if (tolerance == NULL && has_default_tolerance_) {
+ tolerance = &default_tolerance_;
+ }
+ if (tolerance == NULL) {
+ return MathUtil::AlmostEquals(value_1, value_2);
+ } else {
+ // Use user-provided fraction and margin. Since they are stored as
+ // doubles, we explicitely cast them to types of values provided. This
+ // is very likely to fail if provided values are not numeric.
+ return MathUtil::WithinFractionOrMargin(
+ value_1, value_2, static_cast<T>(tolerance->fraction),
+ static_cast<T>(tolerance->margin));
+ }
+ }
+}
+
+FieldComparator::ComparisonResult DefaultFieldComparator::ResultFromBoolean(
+ bool boolean_result) const {
+ return boolean_result ? FieldComparator::SAME : FieldComparator::DIFFERENT;
+}
+
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/field_comparator.h b/src/google/protobuf/util/field_comparator.h
new file mode 100644
index 00000000..ee676265
--- /dev/null
+++ b/src/google/protobuf/util/field_comparator.h
@@ -0,0 +1,259 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: ksroka@google.com (Krzysztof Sroka)
+
+#ifndef GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
+#define GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+class Message;
+class EnumValueDescriptor;
+class FieldDescriptor;
+
+namespace util {
+
+class FieldContext;
+
+// Base class specifying the interface for comparing protocol buffer fields.
+// Regular users should consider using or subclassing DefaultFieldComparator
+// rather than this interface.
+// Currently, this does not support comparing unknown fields.
+class LIBPROTOBUF_EXPORT FieldComparator {
+ public:
+ FieldComparator();
+ virtual ~FieldComparator();
+
+ enum ComparisonResult {
+ SAME, // Compared fields are equal. In case of comparing submessages,
+ // user should not recursively compare their contents.
+ DIFFERENT, // Compared fields are different. In case of comparing
+ // submessages, user should not recursively compare their
+ // contents.
+ RECURSE, // Compared submessages need to be compared recursively.
+ // FieldComparator does not specify the semantics of recursive
+ // comparison. This value should not be returned for simple
+ // values.
+ };
+
+ // Compares the values of a field in two protocol buffer messages.
+ // Returns SAME or DIFFERENT for simple values, and SAME, DIFFERENT or RECURSE
+ // for submessages. Returning RECURSE for fields not being submessages is
+ // illegal.
+ // In case the given FieldDescriptor points to a repeated field, the indices
+ // need to be valid. Otherwise they should be ignored.
+ //
+ // FieldContext contains information about the specific instances of the
+ // fields being compared, versus FieldDescriptor which only contains general
+ // type information about the fields.
+ virtual ComparisonResult Compare(
+ const google::protobuf::Message& message_1,
+ const google::protobuf::Message& message_2,
+ const google::protobuf::FieldDescriptor* field,
+ int index_1, int index_2,
+ const google::protobuf::util::FieldContext* field_context) = 0;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldComparator);
+};
+
+// Basic implementation of FieldComparator. Supports four modes of floating
+// point value comparison: exact, approximate using MathUtil::AlmostEqual
+// method, and arbitrarilly precise using MathUtil::WithinFracionOrMargin.
+class LIBPROTOBUF_EXPORT DefaultFieldComparator : public FieldComparator {
+ public:
+ enum FloatComparison {
+ EXACT, // Floats and doubles are compared exactly.
+ APPROXIMATE, // Floats and doubles are compared using the
+ // MathUtil::AlmostEqual method or
+ // MathUtil::WithinFractionOrMargin method.
+ // TODO(ksroka): Introduce third value to differenciate uses of AlmostEqual
+ // and WithinFractionOrMargin.
+ };
+
+ // Creates new comparator with float comparison set to EXACT.
+ DefaultFieldComparator();
+
+ virtual ~DefaultFieldComparator();
+
+ virtual ComparisonResult Compare(
+ const google::protobuf::Message& message_1,
+ const google::protobuf::Message& message_2,
+ const google::protobuf::FieldDescriptor* field,
+ int index_1, int index_2,
+ const google::protobuf::util::FieldContext* field_context);
+
+ void set_float_comparison(FloatComparison float_comparison) {
+ float_comparison_ = float_comparison;
+ }
+
+ FloatComparison float_comparison() const {
+ return float_comparison_;
+ }
+
+ // Set whether the FieldComparator shall treat floats or doubles that are both
+ // NaN as equal (treat_nan_as_equal = true) or as different
+ // (treat_nan_as_equal = false). Default is treating NaNs always as different.
+ void set_treat_nan_as_equal(bool treat_nan_as_equal) {
+ treat_nan_as_equal_ = treat_nan_as_equal;
+ }
+
+ bool treat_nan_as_equal() const {
+ return treat_nan_as_equal_;
+ }
+
+ // Sets the fraction and margin for the float comparison of a given field.
+ // Uses MathUtil::WithinFractionOrMargin to compare the values.
+ //
+ // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or
+ // field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT
+ // REQUIRES: float_comparison_ == APPROXIMATE
+ void SetFractionAndMargin(const FieldDescriptor* field, double fraction,
+ double margin);
+
+ // Sets the fraction and margin for the float comparison of all float and
+ // double fields, unless a field has been given a specific setting via
+ // SetFractionAndMargin() above.
+ // Uses MathUtil::WithinFractionOrMargin to compare the values.
+ //
+ // REQUIRES: float_comparison_ == APPROXIMATE
+ void SetDefaultFractionAndMargin(double fraction, double margin);
+
+ private:
+ // Defines the tolerance for floating point comparison (fraction and margin).
+ struct Tolerance {
+ double fraction;
+ double margin;
+ Tolerance()
+ : fraction(0.0),
+ margin(0.0) {}
+ Tolerance(double f, double m)
+ : fraction(f),
+ margin(m) {}
+ };
+
+ // Defines the map to store the tolerances for floating point comparison.
+ typedef map<const FieldDescriptor*, Tolerance> ToleranceMap;
+
+ // The following methods get executed when CompareFields is called for the
+ // basic types (instead of submessages). They return true on success. One
+ // can use ResultFromBoolean() to convert that boolean to a ComparisonResult
+ // value.
+ bool CompareBool(const google::protobuf::FieldDescriptor& field,
+ bool value_1, bool value_2) {
+ return value_1 == value_2;
+ }
+
+ // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and
+ // CompareFloat.
+ bool CompareDouble(const google::protobuf::FieldDescriptor& field,
+ double value_1, double value_2);
+
+ bool CompareEnum(const google::protobuf::FieldDescriptor& field,
+ const EnumValueDescriptor* value_1,
+ const EnumValueDescriptor* value_2);
+
+ // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and
+ // CompareFloat.
+ bool CompareFloat(const google::protobuf::FieldDescriptor& field,
+ float value_1, float value_2);
+
+ bool CompareInt32(const google::protobuf::FieldDescriptor& field,
+ int32 value_1, int32 value_2) {
+ return value_1 == value_2;
+ }
+
+ bool CompareInt64(const google::protobuf::FieldDescriptor& field,
+ int64 value_1, int64 value_2) {
+ return value_1 == value_2;
+ }
+
+ bool CompareString(const google::protobuf::FieldDescriptor& field,
+ const string& value_1, const string& value_2) {
+ return value_1 == value_2;
+ }
+
+ bool CompareUInt32(const google::protobuf::FieldDescriptor& field,
+ uint32 value_1, uint32 value_2) {
+ return value_1 == value_2;
+ }
+
+ bool CompareUInt64(const google::protobuf::FieldDescriptor& field,
+ uint64 value_1, uint64 value_2) {
+ return value_1 == value_2;
+ }
+
+ // This function is used by CompareDouble and CompareFloat to avoid code
+ // duplication. There are no checks done against types of the values passed,
+ // but it's likely to fail if passed non-numeric arguments.
+ template<typename T>
+ bool CompareDoubleOrFloat(const google::protobuf::FieldDescriptor& field,
+ T value_1, T value_2);
+
+ // Returns FieldComparator::SAME if boolean_result is true and
+ // FieldComparator::DIFFERENT otherwise.
+ ComparisonResult ResultFromBoolean(bool boolean_result) const;
+
+ FloatComparison float_comparison_;
+
+ // If true, floats and doubles that are both NaN are considered to be
+ // equal. Otherwise, two floats or doubles that are NaN are considered to be
+ // different.
+ bool treat_nan_as_equal_;
+
+ // True iff default_tolerance_ has been explicitly set.
+ //
+ // If false, then the default tolerance for flaots and doubles is that which
+ // is used by MathUtil::AlmostEquals().
+ bool has_default_tolerance_;
+
+ // Default float/double tolerance. Only meaningful if
+ // has_default_tolerance_ == true.
+ Tolerance default_tolerance_;
+
+ // Field-specific float/double tolerances, which override any default for
+ // those particular fields.
+ ToleranceMap map_tolerance_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultFieldComparator);
+};
+
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
diff --git a/src/google/protobuf/util/field_comparator_test.cc b/src/google/protobuf/util/field_comparator_test.cc
new file mode 100644
index 00000000..748c7d11
--- /dev/null
+++ b/src/google/protobuf/util/field_comparator_test.cc
@@ -0,0 +1,483 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: ksroka@google.com (Krzysztof Sroka)
+
+#include <google/protobuf/util/field_comparator.h>
+
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/mathutil.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace {
+
+using protobuf_unittest::TestAllTypes;
+
+class DefaultFieldComparatorTest : public ::testing::Test {
+ protected:
+ void SetUp() {
+ descriptor_ = TestAllTypes::descriptor();
+ }
+
+ const Descriptor* descriptor_;
+ DefaultFieldComparator comparator_;
+ TestAllTypes message_1_;
+ TestAllTypes message_2_;
+};
+
+TEST_F(DefaultFieldComparatorTest, RecursesIntoGroup) {
+ const FieldDescriptor* field =
+ descriptor_->FindFieldByName("optionalgroup");
+ EXPECT_EQ(FieldComparator::RECURSE,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, RecursesIntoNestedMessage) {
+ const FieldDescriptor* field =
+ descriptor_->FindFieldByName("optional_nested_message");
+ EXPECT_EQ(FieldComparator::RECURSE,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, RecursesIntoForeignMessage) {
+ const FieldDescriptor* field =
+ descriptor_->FindFieldByName("optional_foreign_message");
+ EXPECT_EQ(FieldComparator::RECURSE,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, Int32Comparison) {
+ const FieldDescriptor* field = descriptor_->FindFieldByName("optional_int32");
+ message_1_.set_optional_int32(1);
+ message_2_.set_optional_int32(1);
+
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+
+ message_2_.set_optional_int32(-1);
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, Int64Comparison) {
+ const FieldDescriptor* field = descriptor_->FindFieldByName("optional_int64");
+ message_1_.set_optional_int64(1L);
+ message_2_.set_optional_int64(1L);
+
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+
+ message_2_.set_optional_int64(-1L);
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, UInt32Comparison) {
+ const FieldDescriptor* field =
+ descriptor_->FindFieldByName("optional_uint32");
+ message_1_.set_optional_uint32(1);
+ message_2_.set_optional_uint32(1);
+
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+
+ message_2_.set_optional_uint32(2);
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, UInt64Comparison) {
+ const FieldDescriptor* field =
+ descriptor_->FindFieldByName("optional_uint64");
+ message_1_.set_optional_uint64(1L);
+ message_2_.set_optional_uint64(1L);
+
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+
+ message_2_.set_optional_uint64(2L);
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, BooleanComparison) {
+ const FieldDescriptor* field =
+ descriptor_->FindFieldByName("optional_bool");
+ message_1_.set_optional_bool(true);
+ message_2_.set_optional_bool(true);
+
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+
+ message_2_.set_optional_bool(false);
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, EnumComparison) {
+ const FieldDescriptor* field =
+ descriptor_->FindFieldByName("optional_nested_enum");
+ message_1_.set_optional_nested_enum(TestAllTypes::BAR);
+ message_2_.set_optional_nested_enum(TestAllTypes::BAR);
+
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+
+ message_2_.set_optional_nested_enum(TestAllTypes::BAZ);
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, StringComparison) {
+ const FieldDescriptor* field =
+ descriptor_->FindFieldByName("optional_string");
+ message_1_.set_optional_string("foo");
+ message_2_.set_optional_string("foo");
+
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+
+ message_2_.set_optional_string("bar");
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonExact) {
+ const FieldDescriptor* field_float =
+ descriptor_->FindFieldByName("optional_float");
+ const FieldDescriptor* field_double =
+ descriptor_->FindFieldByName("optional_double");
+
+ message_1_.set_optional_float(0.1f);
+ message_2_.set_optional_float(0.1f);
+ message_1_.set_optional_double(0.1);
+ message_2_.set_optional_double(0.1);
+
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+
+ message_2_.set_optional_float(0.2f);
+ message_2_.set_optional_double(0.2);
+
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonApproximate) {
+ const FieldDescriptor* field_float =
+ descriptor_->FindFieldByName("optional_float");
+ const FieldDescriptor* field_double =
+ descriptor_->FindFieldByName("optional_double");
+
+ message_1_.set_optional_float(2.300005f);
+ message_2_.set_optional_float(2.300006f);
+ message_1_.set_optional_double(2.3000000000000003);
+ message_2_.set_optional_double(2.3000000000000007);
+
+ // Approximate comparison depends on MathUtil, so we assert on MathUtil
+ // results first to check if that's where the failure was introduced.
+ ASSERT_NE(message_1_.optional_float(), message_2_.optional_float());
+ ASSERT_NE(message_1_.optional_double(), message_2_.optional_double());
+ ASSERT_TRUE(MathUtil::AlmostEquals(message_1_.optional_float(),
+ message_2_.optional_float()));
+ ASSERT_TRUE(MathUtil::AlmostEquals(message_1_.optional_double(),
+ message_2_.optional_double()));
+
+ // DefaultFieldComparator's default float comparison mode is EXACT.
+ ASSERT_EQ(DefaultFieldComparator::EXACT, comparator_.float_comparison());
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+
+ comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
+
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonTreatNaNsAsEqual) {
+ const FieldDescriptor* field_float =
+ descriptor_->FindFieldByName("optional_float");
+ const FieldDescriptor* field_double =
+ descriptor_->FindFieldByName("optional_double");
+
+ message_1_.set_optional_float(MathLimits<float>::kNaN);
+ message_2_.set_optional_float(MathLimits<float>::kNaN);
+ message_1_.set_optional_double(MathLimits<double>::kNaN);
+ message_2_.set_optional_double(MathLimits<double>::kNaN);
+
+ // DefaultFieldComparator's default float comparison mode is EXACT with
+ // treating NaNs as different.
+ ASSERT_EQ(DefaultFieldComparator::EXACT, comparator_.float_comparison());
+ ASSERT_EQ(false, comparator_.treat_nan_as_equal());
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+ comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+
+ comparator_.set_treat_nan_as_equal(true);
+ ASSERT_EQ(true, comparator_.treat_nan_as_equal());
+ comparator_.set_float_comparison(DefaultFieldComparator::EXACT);
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+ comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest,
+ FloatingPointComparisonWithinFractionOrMargin) {
+ const FieldDescriptor* field_float =
+ descriptor_->FindFieldByName("optional_float");
+ const FieldDescriptor* field_double =
+ descriptor_->FindFieldByName("optional_double");
+
+ message_1_.set_optional_float(100.0f);
+ message_2_.set_optional_float(109.9f);
+ message_1_.set_optional_double(100.0);
+ message_2_.set_optional_double(109.9);
+
+ comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+
+ // Should fail since the fraction is too low.
+ comparator_.SetFractionAndMargin(field_float, 0.01, 0.0);
+ comparator_.SetFractionAndMargin(field_double, 0.01, 0.0);
+
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+
+ // Should fail since the margin is too low.
+ comparator_.SetFractionAndMargin(field_float, 0.0, 9.0);
+ comparator_.SetFractionAndMargin(field_double, 0.0, 9.0);
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+
+ // Should succeed since the fraction is high enough.
+ comparator_.SetFractionAndMargin(field_float, 0.2, 0.0);
+ comparator_.SetFractionAndMargin(field_double, 0.2, 0.0);
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+
+ // Should succeed since the margin is high enough.
+ comparator_.SetFractionAndMargin(field_float, 0.0, 10.0);
+ comparator_.SetFractionAndMargin(field_double, 0.0, 10.0);
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+
+ // Setting values for one of the fields should not affect the other.
+ comparator_.SetFractionAndMargin(field_double, 0.0, 0.0);
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+
+ // +inf should be equal even though they are not technically within margin or
+ // fraction.
+ message_1_.set_optional_float(numeric_limits<float>::infinity());
+ message_2_.set_optional_float(numeric_limits<float>::infinity());
+ message_1_.set_optional_double(numeric_limits<double>::infinity());
+ message_2_.set_optional_double(numeric_limits<double>::infinity());
+ comparator_.SetFractionAndMargin(field_float, 0.0, 0.0);
+ comparator_.SetFractionAndMargin(field_double, 0.0, 0.0);
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+
+ // -inf should be equal even though they are not technically within margin or
+ // fraction.
+ message_1_.set_optional_float(-numeric_limits<float>::infinity());
+ message_2_.set_optional_float(-numeric_limits<float>::infinity());
+ message_1_.set_optional_double(-numeric_limits<double>::infinity());
+ message_2_.set_optional_double(-numeric_limits<double>::infinity());
+ comparator_.SetFractionAndMargin(field_float, 0.0, 0.0);
+ comparator_.SetFractionAndMargin(field_double, 0.0, 0.0);
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+}
+
+TEST_F(DefaultFieldComparatorTest,
+ FloatingPointComparisonWithinDefaultFractionOrMargin) {
+ const FieldDescriptor* field_float =
+ descriptor_->FindFieldByName("optional_float");
+ const FieldDescriptor* field_double =
+ descriptor_->FindFieldByName("optional_double");
+
+ message_1_.set_optional_float(100.0f);
+ message_2_.set_optional_float(109.9f);
+ message_1_.set_optional_double(100.0);
+ message_2_.set_optional_double(109.9);
+
+ comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+
+ // Set default fraction and margin.
+ comparator_.SetDefaultFractionAndMargin(0.01, 0.0);
+
+ // Float comparisons should fail since the fraction is too low.
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+
+ // Set field-specific fraction and margin for one field (field_float) but not
+ // the other (field_double)
+ comparator_.SetFractionAndMargin(field_float, 0.2, 0.0);
+
+ // The field with the override should succeed, since its field-specific
+ // fraction is high enough.
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ // The field with no override should fail, since the default fraction is too
+ // low
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+
+ // Set the default fraction and margin high enough so that fields that use
+ // the default should succeed
+ comparator_.SetDefaultFractionAndMargin(0.2, 0.0);
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+
+ // The field with an override should still be OK
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+
+ // Set fraction and margin for the field with an override to be too low
+ comparator_.SetFractionAndMargin(field_float, 0.01, 0.0);
+
+ // Now our default is high enough but field_float's override is too low.
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_,
+ field_float, -1, -1, NULL));
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_,
+ field_double, -1, -1, NULL));
+}
+
+// Simple test checking whether we compare values at correct indices.
+TEST_F(DefaultFieldComparatorTest, RepeatedFieldComparison) {
+ const FieldDescriptor* field =
+ descriptor_->FindFieldByName("repeated_string");
+
+ message_1_.add_repeated_string("foo");
+ message_1_.add_repeated_string("bar");
+ message_2_.add_repeated_string("bar");
+ message_2_.add_repeated_string("baz");
+
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_, field, 0, 0, NULL));
+ EXPECT_EQ(FieldComparator::DIFFERENT,
+ comparator_.Compare(message_1_, message_2_, field, 1, 1, NULL));
+ EXPECT_EQ(FieldComparator::SAME,
+ comparator_.Compare(message_1_, message_2_, field, 1, 0, NULL));
+}
+
+} // namespace util
+} // namespace protobuf
+} // namespace
+} // namespace google
diff --git a/src/google/protobuf/util/internal/constants.h b/src/google/protobuf/util/internal/constants.h
new file mode 100644
index 00000000..0cb8f6e1
--- /dev/null
+++ b/src/google/protobuf/util/internal/constants.h
@@ -0,0 +1,93 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__
+
+#include <google/protobuf/stubs/common.h>
+
+// This file contains constants used by //net/proto2/util/converter.
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+// Prefix for type URLs.
+const char kTypeServiceBaseUrl[] = "type.googleapis.com";
+
+// Format string for RFC3339 timestamp formatting.
+const char kRfc3339TimeFormat[] = "%Y-%m-%dT%H:%M:%S";
+
+// Minimum seconds allowed in a google.protobuf.TimeStamp or Duration value.
+const int64 kMinSeconds = -315576000000;
+
+// Maximum seconds allowed in a google.protobuf.TimeStamp or Duration value.
+const int64 kMaxSeconds = 315576000000;
+
+// Nano seconds in a second.
+const int32 kNanosPerSecond = 1000000000;
+
+// Type url representing NULL values in google.protobuf.Struct type.
+const char kStructNullValueTypeUrl[] =
+ "type.googleapis.com/google.protobuf.NullValue";
+
+// Type string for google.protobuf.Struct
+const char kStructType[] = "google.protobuf.Struct";
+
+// Type string for struct.proto's google.protobuf.Value value type.
+const char kStructValueType[] = "google.protobuf.Value";
+
+// Type string for struct.proto's google.protobuf.ListValue value type.
+const char kStructListValueType[] = "google.protobuf.ListValue";
+
+// Type string for google.protobuf.Timestamp
+const char kTimestampType[] = "google.protobuf.Timestamp";
+
+// Type string for google.protobuf.Duration
+const char kDurationType[] = "google.protobuf.Duration";
+
+// Type URL for struct value type google.protobuf.Value
+const char kStructValueTypeUrl[] = "type.googleapis.com/google.protobuf.Value";
+
+// Type URL for struct value type google.protobuf.Value
+const char kStructTypeUrl[] = "type.googleapis.com/google.protobuf.Struct";
+
+// Type string for google.protobuf.Any
+const char kAnyType[] = "google.protobuf.Any";
+
+// The type URL of google.protobuf.FieldMask;
+const char kFieldMaskTypeUrl[] =
+ "type.googleapis.com/google.protobuf.FieldMask";
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__
diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc
new file mode 100644
index 00000000..944fb2e3
--- /dev/null
+++ b/src/google/protobuf/util/internal/datapiece.cc
@@ -0,0 +1,286 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/datapiece.h>
+
+#include <google/protobuf/struct.pb.h>
+#include <google/protobuf/type.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/mathutil.h>
+#include <google/protobuf/stubs/mathlimits.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+using google::protobuf::EnumDescriptor;
+using google::protobuf::EnumValueDescriptor;
+;
+;
+using util::error::Code;
+using util::Status;
+using util::StatusOr;
+
+namespace {
+
+inline Status InvalidArgument(StringPiece value_str) {
+ return Status(util::error::INVALID_ARGUMENT, value_str);
+}
+
+// For general conversion between
+// int32, int64, uint32, uint64, double and float
+// except conversion between double and float.
+template <typename To, typename From>
+StatusOr<To> NumberConvertAndCheck(From before) {
+ if (::google::protobuf::internal::is_same<From, To>::value) return before;
+ To after = static_cast<To>(before);
+ if (after == before &&
+ MathUtil::Sign<From>(before) == MathUtil::Sign<To>(after)) {
+ return after;
+ } else {
+ return InvalidArgument(::google::protobuf::internal::is_integral<From>::value
+ ? ValueAsString(before)
+ : ::google::protobuf::internal::is_same<From, double>::value
+ ? DoubleAsString(before)
+ : FloatAsString(before));
+ }
+}
+
+// For conversion between double and float only.
+template <typename To, typename From>
+StatusOr<To> FloatingPointConvertAndCheck(From before) {
+ if (MathLimits<From>::IsNaN(before)) return std::numeric_limits<To>::quiet_NaN();
+
+ To after = static_cast<To>(before);
+ if (MathUtil::AlmostEquals<To>(after, before)) {
+ return after;
+ } else {
+ return InvalidArgument(::google::protobuf::internal::is_same<From, double>::value
+ ? DoubleAsString(before)
+ : FloatAsString(before));
+ }
+}
+
+} // namespace
+
+StatusOr<int32> DataPiece::ToInt32() const {
+ if (type_ == TYPE_STRING) {
+ return StringToNumber<int32>(safe_strto32);
+ }
+ return GenericConvert<int32>();
+}
+
+StatusOr<uint32> DataPiece::ToUint32() const {
+ if (type_ == TYPE_STRING) {
+ return StringToNumber<uint32>(safe_strtou32);
+ }
+ return GenericConvert<uint32>();
+}
+
+StatusOr<int64> DataPiece::ToInt64() const {
+ if (type_ == TYPE_STRING) {
+ return StringToNumber<int64>(safe_strto64);
+ }
+ return GenericConvert<int64>();
+}
+
+StatusOr<uint64> DataPiece::ToUint64() const {
+ if (type_ == TYPE_STRING) {
+ return StringToNumber<uint64>(safe_strtou64);
+ }
+ return GenericConvert<uint64>();
+}
+
+StatusOr<double> DataPiece::ToDouble() const {
+ if (type_ == TYPE_FLOAT) {
+ return FloatingPointConvertAndCheck<double, float>(float_);
+ }
+ if (type_ == TYPE_STRING) {
+ if (str_ == "Infinity") return std::numeric_limits<double>::infinity();
+ if (str_ == "-Infinity") return -std::numeric_limits<double>::infinity();
+ if (str_ == "NaN") return std::numeric_limits<double>::quiet_NaN();
+ return StringToNumber<double>(safe_strtod);
+ }
+ return GenericConvert<double>();
+}
+
+StatusOr<float> DataPiece::ToFloat() const {
+ if (type_ == TYPE_DOUBLE) {
+ return FloatingPointConvertAndCheck<float, double>(double_);
+ }
+ if (type_ == TYPE_STRING) {
+ if (str_ == "Infinity") return std::numeric_limits<float>::infinity();
+ if (str_ == "-Infinity") return -std::numeric_limits<float>::infinity();
+ if (str_ == "NaN") return std::numeric_limits<float>::quiet_NaN();
+ // SafeStrToFloat() is used instead of safe_strtof() because the later
+ // does not fail on inputs like SimpleDtoa(DBL_MAX).
+ return StringToNumber<float>(SafeStrToFloat);
+ }
+ return GenericConvert<float>();
+}
+
+StatusOr<bool> DataPiece::ToBool() const {
+ switch (type_) {
+ case TYPE_BOOL:
+ return bool_;
+ case TYPE_STRING:
+ return StringToNumber<bool>(safe_strtob);
+ default:
+ return InvalidArgument(
+ ValueAsStringOrDefault("Wrong type. Cannot convert to Bool."));
+ }
+}
+
+StatusOr<string> DataPiece::ToString() const {
+ switch (type_) {
+ case TYPE_STRING:
+ return str_.ToString();
+ case TYPE_BYTES: {
+ string base64;
+ WebSafeBase64Escape(str_, &base64);
+ return base64;
+ }
+ default:
+ return InvalidArgument(
+ ValueAsStringOrDefault("Cannot convert to string."));
+ }
+}
+
+string DataPiece::ValueAsStringOrDefault(StringPiece default_string) const {
+ switch (type_) {
+ case TYPE_INT32:
+ return SimpleItoa(i32_);
+ case TYPE_INT64:
+ return SimpleItoa(i64_);
+ case TYPE_UINT32:
+ return SimpleItoa(u32_);
+ case TYPE_UINT64:
+ return SimpleItoa(u64_);
+ case TYPE_DOUBLE:
+ return DoubleAsString(double_);
+ case TYPE_FLOAT:
+ return FloatAsString(float_);
+ case TYPE_BOOL:
+ return SimpleBtoa(bool_);
+ case TYPE_STRING:
+ return StrCat("\"", str_.ToString(), "\"");
+ case TYPE_BYTES: {
+ string base64;
+ WebSafeBase64Escape(str_, &base64);
+ return StrCat("\"", base64, "\"");
+ }
+ case TYPE_NULL:
+ return "null";
+ default:
+ return default_string.ToString();
+ }
+}
+
+StatusOr<string> DataPiece::ToBytes() const {
+ if (type_ == TYPE_BYTES) return str_.ToString();
+ if (type_ == TYPE_STRING) {
+ string decoded;
+ if (!WebSafeBase64Unescape(str_, &decoded)) {
+ if (!Base64Unescape(str_, &decoded)) {
+ return InvalidArgument(
+ ValueAsStringOrDefault("Invalid data in input."));
+ }
+ }
+ return decoded;
+ } else {
+ return InvalidArgument(ValueAsStringOrDefault(
+ "Wrong type. Only String or Bytes can be converted to Bytes."));
+ }
+}
+
+StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type) const {
+ if (type_ == TYPE_NULL) return google::protobuf::NULL_VALUE;
+
+ if (type_ == TYPE_STRING) {
+ // First try the given value as a name.
+ string enum_name = str_.ToString();
+ const google::protobuf::EnumValue* value =
+ FindEnumValueByNameOrNull(enum_type, enum_name);
+ if (value != NULL) return value->number();
+ // Next try a normalized name.
+ for (string::iterator it = enum_name.begin(); it != enum_name.end(); ++it) {
+ *it = *it == '-' ? '_' : ascii_toupper(*it);
+ }
+ value = FindEnumValueByNameOrNull(enum_type, enum_name);
+ if (value != NULL) return value->number();
+ } else {
+ StatusOr<int32> value = ToInt32();
+ if (value.ok()) {
+ if (const google::protobuf::EnumValue* enum_value =
+ FindEnumValueByNumberOrNull(enum_type, value.ValueOrDie())) {
+ return enum_value->number();
+ }
+ }
+ }
+ return InvalidArgument(
+ ValueAsStringOrDefault("Cannot find enum with given value."));
+}
+
+template <typename To>
+StatusOr<To> DataPiece::GenericConvert() const {
+ switch (type_) {
+ case TYPE_INT32:
+ return NumberConvertAndCheck<To, int32>(i32_);
+ case TYPE_INT64:
+ return NumberConvertAndCheck<To, int64>(i64_);
+ case TYPE_UINT32:
+ return NumberConvertAndCheck<To, uint32>(u32_);
+ case TYPE_UINT64:
+ return NumberConvertAndCheck<To, uint64>(u64_);
+ case TYPE_DOUBLE:
+ return NumberConvertAndCheck<To, double>(double_);
+ case TYPE_FLOAT:
+ return NumberConvertAndCheck<To, float>(float_);
+ default: // TYPE_ENUM, TYPE_STRING, TYPE_CORD, TYPE_BOOL
+ return InvalidArgument(ValueAsStringOrDefault(
+ "Wrong type. Bool, Enum, String and Cord not supported in "
+ "GenericConvert."));
+ }
+}
+
+template <typename To>
+StatusOr<To> DataPiece::StringToNumber(bool (*func)(StringPiece, To*)) const {
+ To result;
+ if (func(str_, &result)) return result;
+ return InvalidArgument(StrCat("\"", str_.ToString(), "\""));
+}
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/datapiece.h b/src/google/protobuf/util/internal/datapiece.h
new file mode 100644
index 00000000..30947252
--- /dev/null
+++ b/src/google/protobuf/util/internal/datapiece.h
@@ -0,0 +1,212 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/statusor.h>
+
+
+namespace google {
+namespace protobuf {
+class Enum;
+} // namespace protobuf
+
+
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// Container for a single piece of data together with its data type.
+//
+// For primitive types (int32, int64, uint32, uint64, double, float, bool),
+// the data is stored by value.
+//
+// For string, a StringPiece is stored. For Cord, a pointer to Cord is stored.
+// Just like StringPiece, the DataPiece class does not own the storage for
+// the actual string or Cord, so it is the user's responsiblity to guarantee
+// that the underlying storage is still valid when the DataPiece is accessed.
+class LIBPROTOBUF_EXPORT DataPiece {
+ public:
+ // Identifies data type of the value.
+ // These are the types supported by DataPiece.
+ enum Type {
+ TYPE_INT32 = 1,
+ TYPE_INT64 = 2,
+ TYPE_UINT32 = 3,
+ TYPE_UINT64 = 4,
+ TYPE_DOUBLE = 5,
+ TYPE_FLOAT = 6,
+ TYPE_BOOL = 7,
+ TYPE_ENUM = 8,
+ TYPE_STRING = 9,
+ TYPE_BYTES = 10,
+ TYPE_NULL = 11, // explicit NULL type
+ };
+
+ // Constructors and Destructor
+ explicit DataPiece(const int32 value) : type_(TYPE_INT32), i32_(value) {}
+ explicit DataPiece(const int64 value) : type_(TYPE_INT64), i64_(value) {}
+ explicit DataPiece(const uint32 value) : type_(TYPE_UINT32), u32_(value) {}
+ explicit DataPiece(const uint64 value) : type_(TYPE_UINT64), u64_(value) {}
+ explicit DataPiece(const double value) : type_(TYPE_DOUBLE), double_(value) {}
+ explicit DataPiece(const float value) : type_(TYPE_FLOAT), float_(value) {}
+ explicit DataPiece(const bool value) : type_(TYPE_BOOL), bool_(value) {}
+ explicit DataPiece(StringPiece value)
+ : type_(TYPE_STRING),
+ str_(StringPiecePod::CreateFromStringPiece(value)) {}
+ // Constructor for bytes. The second parameter is not used.
+ explicit DataPiece(StringPiece value, bool dummy)
+ : type_(TYPE_BYTES), str_(StringPiecePod::CreateFromStringPiece(value)) {}
+ DataPiece(const DataPiece& r) : type_(r.type_), str_(r.str_) {}
+ DataPiece& operator=(const DataPiece& x) {
+ type_ = x.type_;
+ str_ = x.str_;
+ return *this;
+ }
+
+ static DataPiece NullData() { return DataPiece(TYPE_NULL, 0); }
+
+ virtual ~DataPiece() {}
+
+ // Accessors
+ Type type() const { return type_; }
+
+ StringPiece str() const {
+ GOOGLE_LOG_IF(DFATAL, type_ != TYPE_STRING) << "Not a string type.";
+ return str_;
+ }
+
+
+ // Parses, casts or converts the value stored in the DataPiece into an int32.
+ util::StatusOr<int32> ToInt32() const;
+
+ // Parses, casts or converts the value stored in the DataPiece into a uint32.
+ util::StatusOr<uint32> ToUint32() const;
+
+ // Parses, casts or converts the value stored in the DataPiece into an int64.
+ util::StatusOr<int64> ToInt64() const;
+
+ // Parses, casts or converts the value stored in the DataPiece into a uint64.
+ util::StatusOr<uint64> ToUint64() const;
+
+ // Parses, casts or converts the value stored in the DataPiece into a double.
+ util::StatusOr<double> ToDouble() const;
+
+ // Parses, casts or converts the value stored in the DataPiece into a float.
+ util::StatusOr<float> ToFloat() const;
+
+ // Parses, casts or converts the value stored in the DataPiece into a bool.
+ util::StatusOr<bool> ToBool() const;
+
+ // Parses, casts or converts the value stored in the DataPiece into a string.
+ util::StatusOr<string> ToString() const;
+
+ // Tries to convert the value contained in this datapiece to string. If the
+ // conversion fails, it returns the default_string.
+ string ValueAsStringOrDefault(StringPiece default_string) const;
+
+ util::StatusOr<string> ToBytes() const;
+
+ // Converts a value into protocol buffer enum number. If the value is a
+ // string, first attempts conversion by name, trying names as follows:
+ // 1) the directly provided string value.
+ // 2) the value upper-cased and replacing '-' by '_'
+ // If the value is not a string, attempts to convert to a 32-bit integer.
+ // If none of these succeeds, returns a conversion error status.
+ util::StatusOr<int> ToEnum(const google::protobuf::Enum* enum_type) const;
+
+ private:
+ // Disallow implicit constructor.
+ DataPiece();
+
+ // Helper to create NULL or ENUM types.
+ DataPiece(Type type, int32 val) : type_(type), i32_(val) {}
+
+ // For numeric conversion between
+ // int32, int64, uint32, uint64, double, float and bool
+ template <typename To>
+ util::StatusOr<To> GenericConvert() const;
+
+ // For conversion from string to
+ // int32, int64, uint32, uint64, double, float and bool
+ template <typename To>
+ util::StatusOr<To> StringToNumber(bool (*func)(StringPiece, To*)) const;
+
+ // Data type for this piece of data.
+ Type type_;
+
+ // StringPiece is not a POD and can not be used in an union (pre C++11). We
+ // need a POD version of it.
+ struct StringPiecePod {
+ const char* data;
+ int size;
+
+ // Create from a StringPiece.
+ static StringPiecePod CreateFromStringPiece(StringPiece str) {
+ StringPiecePod pod;
+ pod.data = str.data();
+ pod.size = str.size();
+ return pod;
+ }
+
+ // Cast to StringPiece.
+ operator StringPiece() const { return StringPiece(data, size); }
+
+ bool operator==(const char* value) const {
+ return StringPiece(data, size) == StringPiece(value);
+ }
+
+ string ToString() const { return string(data, size); }
+ };
+
+ // Stored piece of data.
+ union {
+ const int32 i32_;
+ const int64 i64_;
+ const uint32 u32_;
+ const uint64 u64_;
+ const double double_;
+ const float float_;
+ const bool bool_;
+ StringPiecePod str_;
+ };
+};
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc
new file mode 100644
index 00000000..267e2cd3
--- /dev/null
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc
@@ -0,0 +1,515 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/default_value_objectwriter.h>
+
+#include <google/protobuf/stubs/hash.h>
+
+#include <google/protobuf/util/internal/constants.h>
+#include <google/protobuf/stubs/map_util.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+using util::Status;
+using util::StatusOr;
+namespace converter {
+
+DefaultValueObjectWriter::DefaultValueObjectWriter(
+ TypeResolver* type_resolver, const google::protobuf::Type& type,
+ ObjectWriter* ow)
+ : typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
+ type_(type),
+ disable_normalize_(false),
+ current_(NULL),
+ root_(NULL),
+ ow_(ow) {}
+
+DefaultValueObjectWriter::~DefaultValueObjectWriter() {
+ for (int i = 0; i < string_values_.size(); ++i) {
+ delete string_values_[i];
+ }
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBool(StringPiece name,
+ bool value) {
+ if (current_ == NULL) {
+ ow_->RenderBool(name, value);
+ } else {
+ RenderDataPiece(name, DataPiece(value));
+ }
+ return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt32(
+ StringPiece name, int32 value) {
+ if (current_ == NULL) {
+ ow_->RenderInt32(name, value);
+ } else {
+ RenderDataPiece(name, DataPiece(value));
+ }
+ return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint32(
+ StringPiece name, uint32 value) {
+ if (current_ == NULL) {
+ ow_->RenderUint32(name, value);
+ } else {
+ RenderDataPiece(name, DataPiece(value));
+ }
+ return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt64(
+ StringPiece name, int64 value) {
+ if (current_ == NULL) {
+ ow_->RenderInt64(name, value);
+ } else {
+ RenderDataPiece(name, DataPiece(value));
+ }
+ return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint64(
+ StringPiece name, uint64 value) {
+ if (current_ == NULL) {
+ ow_->RenderUint64(name, value);
+ } else {
+ RenderDataPiece(name, DataPiece(value));
+ }
+ return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderDouble(
+ StringPiece name, double value) {
+ if (current_ == NULL) {
+ ow_->RenderDouble(name, value);
+ } else {
+ RenderDataPiece(name, DataPiece(value));
+ }
+ return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderFloat(
+ StringPiece name, float value) {
+ if (current_ == NULL) {
+ ow_->RenderBool(name, value);
+ } else {
+ RenderDataPiece(name, DataPiece(value));
+ }
+ return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderString(
+ StringPiece name, StringPiece value) {
+ if (current_ == NULL) {
+ ow_->RenderString(name, value);
+ } else {
+ // Since StringPiece is essentially a pointer, takes a copy of "value" to
+ // avoid ownership issues.
+ string_values_.push_back(new string(value.ToString()));
+ RenderDataPiece(name, DataPiece(*string_values_.back()));
+ }
+ return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes(
+ StringPiece name, StringPiece value) {
+ if (current_ == NULL) {
+ ow_->RenderBytes(name, value);
+ } else {
+ RenderDataPiece(name, DataPiece(value));
+ }
+ return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderNull(
+ StringPiece name) {
+ if (current_ == NULL) {
+ ow_->RenderNull(name);
+ } else {
+ RenderDataPiece(name, DataPiece::NullData());
+ }
+ return this;
+}
+
+DefaultValueObjectWriter*
+DefaultValueObjectWriter::DisableCaseNormalizationForNextKey() {
+ disable_normalize_ = true;
+ return this;
+}
+
+DefaultValueObjectWriter::Node::Node(const string& name,
+ const google::protobuf::Type* type,
+ NodeKind kind, const DataPiece& data,
+ bool is_placeholder)
+ : name_(name),
+ type_(type),
+ kind_(kind),
+ disable_normalize_(false),
+ is_any_(false),
+ data_(data),
+ is_placeholder_(is_placeholder) {}
+
+DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild(
+ StringPiece name) {
+ if (name.empty() || kind_ != OBJECT) {
+ return NULL;
+ }
+ for (int i = 0; i < children_.size(); ++i) {
+ Node* child = children_[i];
+ if (child->name() == name) {
+ return child;
+ }
+ }
+ return NULL;
+}
+
+void DefaultValueObjectWriter::Node::WriteTo(ObjectWriter* ow) {
+ if (disable_normalize_) {
+ ow->DisableCaseNormalizationForNextKey();
+ }
+ if (kind_ == PRIMITIVE) {
+ ObjectWriter::RenderDataPieceTo(data_, name_, ow);
+ return;
+ }
+ if (is_placeholder_) {
+ // If is_placeholder_ = true, we didn't see this node in the response, so
+ // skip output.
+ return;
+ }
+ if (kind_ == LIST) {
+ ow->StartList(name_);
+ } else {
+ ow->StartObject(name_);
+ }
+ for (int i = 0; i < children_.size(); ++i) {
+ Node* child = children_[i];
+ child->WriteTo(ow);
+ }
+ if (kind_ == LIST) {
+ ow->EndList();
+ } else {
+ ow->EndObject();
+ }
+}
+
+const google::protobuf::Type* DefaultValueObjectWriter::Node::GetMapValueType(
+ const google::protobuf::Type& found_type, TypeInfo* typeinfo) {
+ // If this field is a map, we should use the type of its "Value" as
+ // the type of the child node.
+ for (int i = 0; i < found_type.fields_size(); ++i) {
+ const google::protobuf::Field& sub_field = found_type.fields(i);
+ if (sub_field.number() != 2) {
+ continue;
+ }
+ if (sub_field.kind() != google::protobuf::Field_Kind_TYPE_MESSAGE) {
+ // This map's value type is not a message type. We don't need to
+ // get the field_type in this case.
+ break;
+ }
+ util::StatusOr<const google::protobuf::Type*> sub_type =
+ typeinfo->ResolveTypeUrl(sub_field.type_url());
+ if (!sub_type.ok()) {
+ GOOGLE_LOG(WARNING) << "Cannot resolve type '" << sub_field.type_url() << "'.";
+ } else {
+ return sub_type.ValueOrDie();
+ }
+ break;
+ }
+ return NULL;
+}
+
+void DefaultValueObjectWriter::Node::PopulateChildren(TypeInfo* typeinfo) {
+ // Ignores well known types that don't require automatically populating their
+ // primitive children. For type "Any", we only populate its children when the
+ // "@type" field is set.
+ // TODO(tsun): remove "kStructValueType" from the list. It's being checked
+ // now because of a bug in the tool-chain that causes the "oneof_index"
+ // of kStructValueType to not be set correctly.
+ if (type_ == NULL || type_->name() == kAnyType ||
+ type_->name() == kStructType || type_->name() == kTimestampType ||
+ type_->name() == kDurationType || type_->name() == kStructValueType) {
+ return;
+ }
+ std::vector<Node*> new_children;
+ hash_map<string, int> orig_children_map;
+
+ // Creates a map of child nodes to speed up lookup.
+ for (int i = 0; i < children_.size(); ++i) {
+ InsertIfNotPresent(&orig_children_map, children_[i]->name_, i);
+ }
+
+ for (int i = 0; i < type_->fields_size(); ++i) {
+ const google::protobuf::Field& field = type_->fields(i);
+ hash_map<string, int>::iterator found =
+ orig_children_map.find(field.name());
+ // If the child field has already been set, we just add it to the new list
+ // of children.
+ if (found != orig_children_map.end()) {
+ new_children.push_back(children_[found->second]);
+ children_[found->second] = NULL;
+ continue;
+ }
+
+ const google::protobuf::Type* field_type = NULL;
+ bool is_map = false;
+ NodeKind kind = PRIMITIVE;
+
+ if (field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) {
+ kind = OBJECT;
+ util::StatusOr<const google::protobuf::Type*> found_result =
+ typeinfo->ResolveTypeUrl(field.type_url());
+ if (!found_result.ok()) {
+ // "field" is of an unknown type.
+ GOOGLE_LOG(WARNING) << "Cannot resolve type '" << field.type_url() << "'.";
+ } else {
+ const google::protobuf::Type* found_type = found_result.ValueOrDie();
+ is_map = IsMap(field, *found_type);
+
+ if (!is_map) {
+ field_type = found_type;
+ } else {
+ // If this field is a map, we should use the type of its "Value" as
+ // the type of the child node.
+ field_type = GetMapValueType(*found_type, typeinfo);
+ kind = MAP;
+ }
+ }
+ }
+ if (!is_map &&
+ field.cardinality() ==
+ google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) {
+ kind = LIST;
+ }
+ // If the child field is of primitive type, sets its data to the default
+ // value of its type.
+ // If oneof_index() != 0, the child field is part of a "oneof", which means
+ // the child field is optional and we shouldn't populate its default value.
+ google::protobuf::scoped_ptr<Node> child(
+ new Node(field.name(), field_type, kind,
+ ((kind == PRIMITIVE && field.oneof_index() == 0)
+ ? CreateDefaultDataPieceForField(field)
+ : DataPiece::NullData()),
+ true));
+ new_children.push_back(child.release());
+ }
+ // Adds all leftover nodes in children_ to the beginning of new_child.
+ for (int i = 0; i < children_.size(); ++i) {
+ if (children_[i] == NULL) {
+ continue;
+ }
+ new_children.insert(new_children.begin(), children_[i]);
+ children_[i] = NULL;
+ }
+ children_.swap(new_children);
+}
+
+void DefaultValueObjectWriter::MaybePopulateChildrenOfAny(Node* node) {
+ // If this is an "Any" node with "@type" already given and no other children
+ // have been added, populates its children.
+ if (node != NULL && node->is_any() && node->type() != NULL &&
+ node->type()->name() != kAnyType && node->number_of_children() == 1) {
+ node->PopulateChildren(typeinfo_.get());
+ }
+}
+
+DataPiece DefaultValueObjectWriter::CreateDefaultDataPieceForField(
+ const google::protobuf::Field& field) {
+ switch (field.kind()) {
+ case google::protobuf::Field_Kind_TYPE_DOUBLE: {
+ return DataPiece(static_cast<double>(0));
+ }
+ case google::protobuf::Field_Kind_TYPE_FLOAT: {
+ return DataPiece(static_cast<float>(0));
+ }
+ case google::protobuf::Field_Kind_TYPE_INT64:
+ case google::protobuf::Field_Kind_TYPE_SINT64:
+ case google::protobuf::Field_Kind_TYPE_SFIXED64: {
+ return DataPiece(static_cast<int64>(0));
+ }
+ case google::protobuf::Field_Kind_TYPE_UINT64:
+ case google::protobuf::Field_Kind_TYPE_FIXED64: {
+ return DataPiece(static_cast<uint64>(0));
+ }
+ case google::protobuf::Field_Kind_TYPE_INT32:
+ case google::protobuf::Field_Kind_TYPE_SINT32:
+ case google::protobuf::Field_Kind_TYPE_SFIXED32: {
+ return DataPiece(static_cast<int32>(0));
+ }
+ case google::protobuf::Field_Kind_TYPE_BOOL: {
+ return DataPiece(false);
+ }
+ case google::protobuf::Field_Kind_TYPE_STRING: {
+ return DataPiece(string());
+ }
+ case google::protobuf::Field_Kind_TYPE_BYTES: {
+ return DataPiece("", false);
+ }
+ case google::protobuf::Field_Kind_TYPE_UINT32:
+ case google::protobuf::Field_Kind_TYPE_FIXED32: {
+ return DataPiece(static_cast<uint32>(0));
+ }
+ default: { return DataPiece::NullData(); }
+ }
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
+ StringPiece name) {
+ if (current_ == NULL) {
+ root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(),
+ false));
+ root_->set_disable_normalize(GetAndResetDisableNormalize());
+ root_->PopulateChildren(typeinfo_.get());
+ current_ = root_.get();
+ return this;
+ }
+ MaybePopulateChildrenOfAny(current_);
+ Node* child = current_->FindChild(name);
+ if (current_->kind() == LIST || current_->kind() == MAP || child == NULL) {
+ // If current_ is a list or a map node, we should create a new child and use
+ // the type of current_ as the type of the new child.
+ google::protobuf::scoped_ptr<Node> node(new Node(
+ name.ToString(), ((current_->kind() == LIST || current_->kind() == MAP)
+ ? current_->type()
+ : NULL),
+ OBJECT, DataPiece::NullData(), false));
+ child = node.get();
+ current_->AddChild(node.release());
+ }
+
+ child->set_is_placeholder(false);
+ child->set_disable_normalize(GetAndResetDisableNormalize());
+ if (child->kind() == OBJECT && child->number_of_children() == 0) {
+ child->PopulateChildren(typeinfo_.get());
+ }
+
+ stack_.push(current_);
+ current_ = child;
+ return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::EndObject() {
+ if (stack_.empty()) {
+ // The root object ends here. Writes out the tree.
+ WriteRoot();
+ return this;
+ }
+ current_ = stack_.top();
+ stack_.pop();
+ return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::StartList(
+ StringPiece name) {
+ if (current_ == NULL) {
+ root_.reset(
+ new Node(name.ToString(), &type_, LIST, DataPiece::NullData(), false));
+ root_->set_disable_normalize(GetAndResetDisableNormalize());
+ current_ = root_.get();
+ return this;
+ }
+ MaybePopulateChildrenOfAny(current_);
+ Node* child = current_->FindChild(name);
+ if (child == NULL || child->kind() != LIST) {
+ GOOGLE_LOG(WARNING) << "Cannot find field '" << name << "'.";
+ google::protobuf::scoped_ptr<Node> node(
+ new Node(name.ToString(), NULL, LIST, DataPiece::NullData(), false));
+ child = node.get();
+ current_->AddChild(node.release());
+ }
+ child->set_is_placeholder(false);
+ child->set_disable_normalize(GetAndResetDisableNormalize());
+
+ stack_.push(current_);
+ current_ = child;
+ return this;
+}
+
+void DefaultValueObjectWriter::WriteRoot() {
+ root_->WriteTo(ow_);
+ root_.reset(NULL);
+ current_ = NULL;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::EndList() {
+ if (stack_.empty()) {
+ WriteRoot();
+ return this;
+ }
+ current_ = stack_.top();
+ stack_.pop();
+ return this;
+}
+
+void DefaultValueObjectWriter::RenderDataPiece(StringPiece name,
+ const DataPiece& data) {
+ MaybePopulateChildrenOfAny(current_);
+ util::StatusOr<string> data_string = data.ToString();
+ if (current_->type() != NULL && current_->type()->name() == kAnyType &&
+ name == "@type" && data_string.ok()) {
+ const string& string_value = data_string.ValueOrDie();
+ // If the type of current_ is "Any" and its "@type" field is being set here,
+ // sets the type of current_ to be the type specified by the "@type".
+ util::StatusOr<const google::protobuf::Type*> found_type =
+ typeinfo_->ResolveTypeUrl(string_value);
+ if (!found_type.ok()) {
+ GOOGLE_LOG(WARNING) << "Failed to resolve type '" << string_value << "'.";
+ } else {
+ current_->set_type(found_type.ValueOrDie());
+ }
+ current_->set_is_any(true);
+ // If the "@type" field is placed after other fields, we should populate
+ // other children of primitive type now. Otherwise, we should wait until the
+ // first value field is rendered before we populate the children, because
+ // the "value" field of a Any message could be omitted.
+ if (current_->number_of_children() > 1 && current_->type() != NULL) {
+ current_->PopulateChildren(typeinfo_.get());
+ }
+ }
+ Node* child = current_->FindChild(name);
+ if (child == NULL || child->kind() != PRIMITIVE) {
+ GOOGLE_LOG(WARNING) << "Cannot find primitive field '" << name << "'.";
+ // No children are found, creates a new child.
+ google::protobuf::scoped_ptr<Node> node(
+ new Node(name.ToString(), NULL, PRIMITIVE, data, false));
+ child = node.get();
+ current_->AddChild(node.release());
+ } else {
+ child->set_data(data);
+ }
+ child->set_disable_normalize(GetAndResetDisableNormalize());
+}
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h
new file mode 100644
index 00000000..759ba91b
--- /dev/null
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.h
@@ -0,0 +1,238 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <stack>
+#include <vector>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/util/internal/type_info.h>
+#include <google/protobuf/util/internal/datapiece.h>
+#include <google/protobuf/util/internal/object_writer.h>
+#include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/stringpiece.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// An ObjectWriter that renders non-repeated primitive fields of proto messages
+// with their default values. DefaultValueObjectWriter holds objects, lists and
+// fields it receives in a tree structure and writes them out to another
+// ObjectWriter when EndObject() is called on the root object. It also writes
+// out all non-repeated primitive fields that haven't been explicitly rendered
+// with their default values (0 for numbers, "" for strings, etc).
+class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
+ public:
+ DefaultValueObjectWriter(TypeResolver* type_resolver,
+ const google::protobuf::Type& type,
+ ObjectWriter* ow);
+
+ virtual ~DefaultValueObjectWriter();
+
+ // ObjectWriter methods.
+ virtual DefaultValueObjectWriter* StartObject(StringPiece name);
+
+ virtual DefaultValueObjectWriter* EndObject();
+
+ virtual DefaultValueObjectWriter* StartList(StringPiece name);
+
+ virtual DefaultValueObjectWriter* EndList();
+
+ virtual DefaultValueObjectWriter* RenderBool(StringPiece name, bool value);
+
+ virtual DefaultValueObjectWriter* RenderInt32(StringPiece name, int32 value);
+
+ virtual DefaultValueObjectWriter* RenderUint32(StringPiece name,
+ uint32 value);
+
+ virtual DefaultValueObjectWriter* RenderInt64(StringPiece name, int64 value);
+
+ virtual DefaultValueObjectWriter* RenderUint64(StringPiece name,
+ uint64 value);
+
+ virtual DefaultValueObjectWriter* RenderDouble(StringPiece name,
+ double value);
+
+ virtual DefaultValueObjectWriter* RenderFloat(StringPiece name, float value);
+
+ virtual DefaultValueObjectWriter* RenderString(StringPiece name,
+ StringPiece value);
+ virtual DefaultValueObjectWriter* RenderBytes(StringPiece name,
+ StringPiece value);
+
+ virtual DefaultValueObjectWriter* RenderNull(StringPiece name);
+
+ virtual DefaultValueObjectWriter* DisableCaseNormalizationForNextKey();
+
+ private:
+ enum NodeKind {
+ PRIMITIVE = 0,
+ OBJECT = 1,
+ LIST = 2,
+ MAP = 3,
+ };
+
+ // "Node" represents a node in the tree that holds the input of
+ // DefaultValueObjectWriter.
+ class Node {
+ public:
+ Node(const string& name, const google::protobuf::Type* type, NodeKind kind,
+ const DataPiece& data, bool is_placeholder);
+ virtual ~Node() {
+ for (int i = 0; i < children_.size(); ++i) {
+ delete children_[i];
+ }
+ }
+
+ // Adds a child to this node. Takes ownership of this child.
+ void AddChild(Node* child) { children_.push_back(child); }
+
+ // Finds the child given its name.
+ Node* FindChild(StringPiece name);
+
+ // Populates children of this Node based on its type. If there are already
+ // children created, they will be merged to the result. Caller should pass
+ // in TypeInfo for looking up types of the children.
+ void PopulateChildren(TypeInfo* typeinfo);
+
+ // If this node is a leaf (has data), writes the current node to the
+ // ObjectWriter; if not, then recursively writes the children to the
+ // ObjectWriter.
+ void WriteTo(ObjectWriter* ow);
+
+ // Accessors
+ const string& name() const { return name_; }
+
+ const google::protobuf::Type* type() { return type_; }
+
+ void set_type(const google::protobuf::Type* type) { type_ = type; }
+
+ NodeKind kind() { return kind_; }
+
+ int number_of_children() { return children_.size(); }
+
+ void set_data(const DataPiece& data) { data_ = data; }
+
+ void set_disable_normalize(bool disable_normalize) {
+ disable_normalize_ = disable_normalize;
+ }
+
+ bool is_any() { return is_any_; }
+
+ void set_is_any(bool is_any) { is_any_ = is_any; }
+
+ void set_is_placeholder(bool is_placeholder) {
+ is_placeholder_ = is_placeholder;
+ }
+
+ private:
+ // Returns the Value Type of a map given the Type of the map entry and a
+ // TypeInfo instance.
+ const google::protobuf::Type* GetMapValueType(
+ const google::protobuf::Type& entry_type, TypeInfo* typeinfo);
+
+ // The name of this node.
+ string name_;
+ // google::protobuf::Type of this node. Owned by TypeInfo.
+ const google::protobuf::Type* type_;
+ // The kind of this node.
+ NodeKind kind_;
+ // Whether to disable case normalization of the name.
+ bool disable_normalize_;
+ // Whether this is a node for "Any".
+ bool is_any_;
+ // The data of this node when it is a leaf node.
+ DataPiece data_;
+ // Children of this node.
+ std::vector<Node*> children_;
+ // Whether this node is a placeholder for an object or list automatically
+ // generated when creating the parent node. Should be set to false after
+ // the parent node's StartObject()/StartList() method is called with this
+ // node's name.
+ bool is_placeholder_;
+ };
+
+ // Populates children of "node" if it is an "any" Node and its real type has
+ // been given.
+ void MaybePopulateChildrenOfAny(Node* node);
+
+ // Writes the root_ node to ow_ and resets the root_ and current_ pointer to
+ // NULL.
+ void WriteRoot();
+
+ // Creates a DataPiece containing the default value of the type of the field.
+ static DataPiece CreateDefaultDataPieceForField(
+ const google::protobuf::Field& field);
+
+ // Returns disable_normalize_ and reset it to false.
+ bool GetAndResetDisableNormalize() {
+ return disable_normalize_ ? (disable_normalize_ = false, true) : false;
+ }
+
+ // Adds or replaces the data_ of a primitive child node.
+ void RenderDataPiece(StringPiece name, const DataPiece& data);
+
+ // Type information for all the types used in the descriptor. Used to find
+ // google::protobuf::Type of nested messages/enums.
+ google::protobuf::scoped_ptr<TypeInfo> typeinfo_;
+ // google::protobuf::Type of the root message type.
+ const google::protobuf::Type& type_;
+ // Holds copies of strings passed to RenderString.
+ vector<string*> string_values_;
+
+ // Whether to disable case normalization of the next node.
+ bool disable_normalize_;
+ // The current Node. Owned by its parents.
+ Node* current_;
+ // The root Node.
+ google::protobuf::scoped_ptr<Node> root_;
+ // The stack to hold the path of Nodes from current_ to root_;
+ std::stack<Node*> stack_;
+
+ ObjectWriter* ow_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultValueObjectWriter);
+};
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
new file mode 100644
index 00000000..593c7105
--- /dev/null
+++ b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
@@ -0,0 +1,139 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/default_value_objectwriter.h>
+#include <google/protobuf/util/internal/expecting_objectwriter.h>
+#include <google/protobuf/util/internal/testdata/default_value_test.pb.h>
+#include <google/protobuf/util/internal/type_info_test_helper.h>
+#include <google/protobuf/util/internal/constants.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+namespace testing {
+
+using google::protobuf::testing::DefaultValueTest;
+
+// Tests to cover some basic DefaultValueObjectWriter use cases. More tests are
+// in the marshalling_test.cc and translator_integration_test.cc.
+class DefaultValueObjectWriterTest
+ : public ::testing::TestWithParam<testing::TypeInfoSource> {
+ protected:
+ DefaultValueObjectWriterTest()
+ : helper_(GetParam()), mock_(), expects_(&mock_) {
+ helper_.ResetTypeInfo(DefaultValueTest::descriptor());
+ testing_.reset(helper_.NewDefaultValueWriter(
+ string(kTypeServiceBaseUrl) + "/" +
+ DefaultValueTest::descriptor()->full_name(),
+ &mock_));
+ }
+
+ virtual ~DefaultValueObjectWriterTest() {}
+
+ TypeInfoTestHelper helper_;
+ MockObjectWriter mock_;
+ ExpectingObjectWriter expects_;
+ google::protobuf::scoped_ptr<DefaultValueObjectWriter> testing_;
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+ DefaultValueObjectWriterTest,
+ ::testing::Values(
+ testing::USE_TYPE_RESOLVER));
+
+TEST_P(DefaultValueObjectWriterTest, Empty) {
+ // Set expectation
+ expects_.StartObject("")
+ ->RenderDouble("double_value", 0.0)
+ ->RenderFloat("float_value", 0.0)
+ ->RenderInt64("int64_value", 0)
+ ->RenderUint64("uint64_value", 0)
+ ->RenderInt32("int32_value", 0)
+ ->RenderUint32("uint32_value", 0)
+ ->RenderBool("bool_value", false)
+ ->RenderString("string_value", "")
+ ->RenderBytes("bytes_value", "")
+ ->EndObject();
+
+ // Actual testing
+ testing_->StartObject("")->EndObject();
+}
+
+TEST_P(DefaultValueObjectWriterTest, NonDefaultDouble) {
+ // Set expectation
+ expects_.StartObject("")
+ ->RenderDouble("double_value", 1.0)
+ ->RenderFloat("float_value", 0.0)
+ ->RenderInt64("int64_value", 0)
+ ->RenderUint64("uint64_value", 0)
+ ->RenderInt32("int32_value", 0)
+ ->RenderUint32("uint32_value", 0)
+ ->RenderBool("bool_value", false)
+ ->RenderString("string_value", "")
+ ->EndObject();
+
+ // Actual testing
+ testing_->StartObject("")->RenderDouble("double_value", 1.0)->EndObject();
+}
+
+TEST_P(DefaultValueObjectWriterTest, ShouldRetainUnknownField) {
+ // Set expectation
+ expects_.StartObject("")
+ ->RenderDouble("double_value", 1.0)
+ ->RenderFloat("float_value", 0.0)
+ ->RenderInt64("int64_value", 0)
+ ->RenderUint64("uint64_value", 0)
+ ->RenderInt32("int32_value", 0)
+ ->RenderUint32("uint32_value", 0)
+ ->RenderBool("bool_value", false)
+ ->RenderString("string_value", "")
+ ->RenderString("unknown", "abc")
+ ->StartObject("unknown_object")
+ ->RenderString("unknown", "def")
+ ->EndObject()
+ ->EndObject();
+
+ // Actual testing
+ testing_->StartObject("")
+ ->RenderDouble("double_value", 1.0)
+ ->RenderString("unknown", "abc")
+ ->StartObject("unknown_object")
+ ->RenderString("unknown", "def")
+ ->EndObject()
+ ->EndObject();
+}
+
+} // namespace testing
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/error_listener.cc b/src/google/protobuf/util/internal/error_listener.cc
new file mode 100644
index 00000000..538307ba
--- /dev/null
+++ b/src/google/protobuf/util/internal/error_listener.cc
@@ -0,0 +1,42 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/error_listener.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/error_listener.h b/src/google/protobuf/util/internal/error_listener.h
new file mode 100644
index 00000000..9b907df5
--- /dev/null
+++ b/src/google/protobuf/util/internal/error_listener.h
@@ -0,0 +1,99 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_ERROR_LISTENER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_ERROR_LISTENER_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/util/internal/location_tracker.h>
+#include <google/protobuf/stubs/stringpiece.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// Interface for error listener.
+class LIBPROTOBUF_EXPORT ErrorListener {
+ public:
+ virtual ~ErrorListener() {}
+
+ // Reports an invalid name at the given location.
+ virtual void InvalidName(const LocationTrackerInterface& loc,
+ StringPiece unknown_name, StringPiece message) = 0;
+
+ // Reports an invalid value for a field.
+ virtual void InvalidValue(const LocationTrackerInterface& loc,
+ StringPiece type_name, StringPiece value) = 0;
+
+ // Reports a missing required field.
+ virtual void MissingField(const LocationTrackerInterface& loc,
+ StringPiece missing_name) = 0;
+
+ protected:
+ ErrorListener() {}
+
+ private:
+ // Do not add any data members to this class.
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorListener);
+};
+
+// An error listener that ignores all errors.
+class LIBPROTOBUF_EXPORT NoopErrorListener : public ErrorListener {
+ public:
+ NoopErrorListener() {}
+ virtual ~NoopErrorListener() {}
+
+ virtual void InvalidName(const LocationTrackerInterface& loc,
+ StringPiece unknown_name, StringPiece message) {}
+
+ virtual void InvalidValue(const LocationTrackerInterface& loc,
+ StringPiece type_name, StringPiece value) {}
+
+ virtual void MissingField(const LocationTrackerInterface& loc,
+ StringPiece missing_name) {}
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NoopErrorListener);
+};
+
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_ERROR_LISTENER_H__
diff --git a/src/google/protobuf/util/internal/expecting_objectwriter.h b/src/google/protobuf/util/internal/expecting_objectwriter.h
new file mode 100644
index 00000000..ae98ddd8
--- /dev/null
+++ b/src/google/protobuf/util/internal/expecting_objectwriter.h
@@ -0,0 +1,238 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_EXPECTING_OBJECTWRITER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_EXPECTING_OBJECTWRITER_H__
+
+// An implementation of ObjectWriter that automatically sets the
+// gmock expectations for the response to a method. Every method
+// returns the object itself for chaining.
+//
+// Usage:
+// // Setup
+// MockObjectWriter mock;
+// ExpectingObjectWriter ow(&mock);
+//
+// // Set expectation
+// ow.StartObject("")
+// ->RenderString("key", "value")
+// ->EndObject();
+//
+// // Actual testing
+// mock.StartObject(StringPiece())
+// ->RenderString("key", "value")
+// ->EndObject();
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/util/internal/object_writer.h>
+#include <gmock/gmock.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+using testing::IsEmpty;
+using testing::NanSensitiveDoubleEq;
+using testing::NanSensitiveFloatEq;
+using testing::Return;
+using testing::StrEq;
+using testing::TypedEq;
+
+class MockObjectWriter : public ObjectWriter {
+ public:
+ MockObjectWriter() {}
+
+ MOCK_METHOD1(StartObject, ObjectWriter*(StringPiece));
+ MOCK_METHOD0(EndObject, ObjectWriter*());
+ MOCK_METHOD1(StartList, ObjectWriter*(StringPiece));
+ MOCK_METHOD0(EndList, ObjectWriter*());
+ MOCK_METHOD2(RenderBool, ObjectWriter*(StringPiece, bool));
+ MOCK_METHOD2(RenderInt32, ObjectWriter*(StringPiece, int32));
+ MOCK_METHOD2(RenderUint32, ObjectWriter*(StringPiece, uint32));
+ MOCK_METHOD2(RenderInt64, ObjectWriter*(StringPiece, int64));
+ MOCK_METHOD2(RenderUint64, ObjectWriter*(StringPiece, uint64));
+ MOCK_METHOD2(RenderDouble, ObjectWriter*(StringPiece, double));
+ MOCK_METHOD2(RenderFloat, ObjectWriter*(StringPiece, float));
+ MOCK_METHOD2(RenderString, ObjectWriter*(StringPiece, StringPiece));
+ MOCK_METHOD2(RenderBytes, ObjectWriter*(StringPiece, StringPiece));
+ MOCK_METHOD1(RenderNull, ObjectWriter*(StringPiece));
+};
+
+class ExpectingObjectWriter : public ObjectWriter {
+ public:
+ explicit ExpectingObjectWriter(MockObjectWriter* mock) : mock_(mock) {}
+
+ virtual ObjectWriter* StartObject(StringPiece name) {
+ (name.empty()
+ ? EXPECT_CALL(*mock_, StartObject(IsEmpty()))
+ : EXPECT_CALL(*mock_, StartObject(StrEq(name.ToString()))))
+ .WillOnce(Return(mock_))
+ .RetiresOnSaturation();
+ return this;
+ }
+
+ virtual ObjectWriter* EndObject() {
+ EXPECT_CALL(*mock_, EndObject())
+ .WillOnce(Return(mock_))
+ .RetiresOnSaturation();
+ return this;
+ }
+
+ virtual ObjectWriter* StartList(StringPiece name) {
+ (name.empty()
+ ? EXPECT_CALL(*mock_, StartList(IsEmpty()))
+ : EXPECT_CALL(*mock_, StartList(StrEq(name.ToString()))))
+ .WillOnce(Return(mock_))
+ .RetiresOnSaturation();
+ return this;
+ }
+
+ virtual ObjectWriter* EndList() {
+ EXPECT_CALL(*mock_, EndList())
+ .WillOnce(Return(mock_))
+ .RetiresOnSaturation();
+ return this;
+ }
+
+ virtual ObjectWriter* RenderBool(StringPiece name, bool value) {
+ (name.empty()
+ ? EXPECT_CALL(*mock_, RenderBool(IsEmpty(), TypedEq<bool>(value)))
+ : EXPECT_CALL(*mock_, RenderBool(StrEq(name.ToString()),
+ TypedEq<bool>(value))))
+ .WillOnce(Return(mock_))
+ .RetiresOnSaturation();
+ return this;
+ }
+
+ virtual ObjectWriter* RenderInt32(StringPiece name, int32 value) {
+ (name.empty()
+ ? EXPECT_CALL(*mock_, RenderInt32(IsEmpty(), TypedEq<int32>(value)))
+ : EXPECT_CALL(*mock_, RenderInt32(StrEq(name.ToString()),
+ TypedEq<int32>(value))))
+ .WillOnce(Return(mock_))
+ .RetiresOnSaturation();
+ return this;
+ }
+
+ virtual ObjectWriter* RenderUint32(StringPiece name, uint32 value) {
+ (name.empty()
+ ? EXPECT_CALL(*mock_, RenderUint32(IsEmpty(), TypedEq<uint32>(value)))
+ : EXPECT_CALL(*mock_, RenderUint32(StrEq(name.ToString()),
+ TypedEq<uint32>(value))))
+ .WillOnce(Return(mock_))
+ .RetiresOnSaturation();
+ return this;
+ }
+
+ virtual ObjectWriter* RenderInt64(StringPiece name, int64 value) {
+ (name.empty()
+ ? EXPECT_CALL(*mock_, RenderInt64(IsEmpty(), TypedEq<int64>(value)))
+ : EXPECT_CALL(*mock_, RenderInt64(StrEq(name.ToString()),
+ TypedEq<int64>(value))))
+ .WillOnce(Return(mock_))
+ .RetiresOnSaturation();
+ return this;
+ }
+
+ virtual ObjectWriter* RenderUint64(StringPiece name, uint64 value) {
+ (name.empty()
+ ? EXPECT_CALL(*mock_, RenderUint64(IsEmpty(), TypedEq<uint64>(value)))
+ : EXPECT_CALL(*mock_, RenderUint64(StrEq(name.ToString()),
+ TypedEq<uint64>(value))))
+ .WillOnce(Return(mock_))
+ .RetiresOnSaturation();
+ return this;
+ }
+
+ virtual ObjectWriter* RenderDouble(StringPiece name, double value) {
+ (name.empty()
+ ? EXPECT_CALL(*mock_, RenderDouble(IsEmpty(),
+ NanSensitiveDoubleEq(value)))
+ : EXPECT_CALL(*mock_, RenderDouble(StrEq(name.ToString()),
+ NanSensitiveDoubleEq(value))))
+ .WillOnce(Return(mock_))
+ .RetiresOnSaturation();
+ return this;
+ }
+
+ virtual ObjectWriter* RenderFloat(StringPiece name, float value) {
+ (name.empty()
+ ? EXPECT_CALL(*mock_, RenderFloat(IsEmpty(),
+ NanSensitiveFloatEq(value)))
+ : EXPECT_CALL(*mock_, RenderFloat(StrEq(name.ToString()),
+ NanSensitiveFloatEq(value))))
+ .WillOnce(Return(mock_))
+ .RetiresOnSaturation();
+ return this;
+ }
+
+ virtual ObjectWriter* RenderString(StringPiece name, StringPiece value) {
+ (name.empty()
+ ? EXPECT_CALL(*mock_, RenderString(IsEmpty(),
+ TypedEq<StringPiece>(value.ToString())))
+ : EXPECT_CALL(*mock_, RenderString(StrEq(name.ToString()),
+ TypedEq<StringPiece>(value.ToString()))))
+ .WillOnce(Return(mock_))
+ .RetiresOnSaturation();
+ return this;
+ }
+ virtual ObjectWriter* RenderBytes(StringPiece name, StringPiece value) {
+ (name.empty()
+ ? EXPECT_CALL(*mock_, RenderBytes(IsEmpty(), TypedEq<StringPiece>(
+ value.ToString())))
+ : EXPECT_CALL(*mock_,
+ RenderBytes(StrEq(name.ToString()),
+ TypedEq<StringPiece>(value.ToString()))))
+ .WillOnce(Return(mock_))
+ .RetiresOnSaturation();
+ return this;
+ }
+
+ virtual ObjectWriter* RenderNull(StringPiece name) {
+ (name.empty() ? EXPECT_CALL(*mock_, RenderNull(IsEmpty()))
+ : EXPECT_CALL(*mock_, RenderNull(StrEq(name.ToString())))
+ .WillOnce(Return(mock_))
+ .RetiresOnSaturation());
+ return this;
+ }
+
+ private:
+ MockObjectWriter* mock_;
+
+ GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ExpectingObjectWriter);
+};
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_EXPECTING_OBJECTWRITER_H__
diff --git a/src/google/protobuf/util/internal/field_mask_utility.cc b/src/google/protobuf/util/internal/field_mask_utility.cc
new file mode 100644
index 00000000..92468959
--- /dev/null
+++ b/src/google/protobuf/util/internal/field_mask_utility.cc
@@ -0,0 +1,228 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/field_mask_utility.h>
+
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/status_macros.h>
+
+namespace google {
+
+namespace protobuf {
+namespace util {
+namespace converter {
+
+namespace {
+inline util::Status CallPathSink(PathSinkCallback path_sink,
+ StringPiece arg) {
+ return path_sink->Run(arg);
+}
+
+util::Status CreatePublicError(util::error::Code code,
+ const string& message) {
+ return util::Status(code, message);
+}
+
+// Appends a FieldMask path segment to a prefix.
+string AppendPathSegmentToPrefix(StringPiece prefix, StringPiece segment) {
+ if (prefix.empty()) {
+ return segment.ToString();
+ }
+ if (segment.empty()) {
+ return prefix.ToString();
+ }
+ // If the segment is a map key, appends it to the prefix without the ".".
+ if (segment.starts_with("[\"")) {
+ return StrCat(prefix, segment);
+ }
+ return StrCat(prefix, ".", segment);
+}
+
+} // namespace
+
+string ConvertFieldMaskPath(const StringPiece path,
+ ConverterCallback converter) {
+ string result;
+ result.reserve(path.size() << 1);
+
+ bool is_quoted = false;
+ bool is_escaping = false;
+ int current_segment_start = 0;
+
+ // Loops until 1 passed the end of the input to make handling the last
+ // segment easier.
+ for (size_t i = 0; i <= path.size(); ++i) {
+ // Outputs quoted string as-is.
+ if (is_quoted) {
+ if (i == path.size()) {
+ break;
+ }
+ result.push_back(path[i]);
+ if (is_escaping) {
+ is_escaping = false;
+ } else if (path[i] == '\\') {
+ is_escaping = true;
+ } else if (path[i] == '\"') {
+ current_segment_start = i + 1;
+ is_quoted = false;
+ }
+ continue;
+ }
+ if (i == path.size() || path[i] == '.' || path[i] == '(' ||
+ path[i] == ')' || path[i] == '\"') {
+ result += converter(
+ path.substr(current_segment_start, i - current_segment_start));
+ if (i < path.size()) {
+ result.push_back(path[i]);
+ }
+ current_segment_start = i + 1;
+ }
+ if (i < path.size() && path[i] == '\"') {
+ is_quoted = true;
+ }
+ }
+ return result;
+}
+
+util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
+ PathSinkCallback path_sink) {
+ stack<string> prefix;
+ int length = paths.length();
+ int previous_position = 0;
+ bool in_map_key = false;
+ bool is_escaping = false;
+ // Loops until 1 passed the end of the input to make the handle of the last
+ // segment easier.
+ for (int i = 0; i <= length; ++i) {
+ if (i != length) {
+ // Skips everything in a map key until we hit the end of it, which is
+ // marked by an un-escaped '"' immediately followed by a ']'.
+ if (in_map_key) {
+ if (is_escaping) {
+ is_escaping = false;
+ continue;
+ }
+ if (paths[i] == '\\') {
+ is_escaping = true;
+ continue;
+ }
+ if (paths[i] != '\"') {
+ continue;
+ }
+ // Un-escaped '"' must be followed with a ']'.
+ if (i >= length - 1 || paths[i + 1] != ']') {
+ return CreatePublicError(
+ util::error::INVALID_ARGUMENT,
+ StrCat("Invalid FieldMask '", paths,
+ "'. Map keys should be represented as [\"some_key\"]."));
+ }
+ // The end of the map key ("\"]") has been found.
+ in_map_key = false;
+ // Skips ']'.
+ i++;
+ // Checks whether the key ends at the end of a path segment.
+ if (i < length - 1 && paths[i + 1] != '.' && paths[i + 1] != ',' &&
+ paths[i + 1] != ')' && paths[i + 1] != '(') {
+ return CreatePublicError(
+ util::error::INVALID_ARGUMENT,
+ StrCat("Invalid FieldMask '", paths,
+ "'. Map keys should be at the end of a path segment."));
+ }
+ is_escaping = false;
+ continue;
+ }
+
+ // We are not in a map key, look for the start of one.
+ if (paths[i] == '[') {
+ if (i >= length - 1 || paths[i + 1] != '\"') {
+ return CreatePublicError(
+ util::error::INVALID_ARGUMENT,
+ StrCat("Invalid FieldMask '", paths,
+ "'. Map keys should be represented as [\"some_key\"]."));
+ }
+ // "[\"" starts a map key.
+ in_map_key = true;
+ i++; // Skips the '\"'.
+ continue;
+ }
+ // If the current character is not a special character (',', '(' or ')'),
+ // continue to the next.
+ if (paths[i] != ',' && paths[i] != ')' && paths[i] != '(') {
+ continue;
+ }
+ }
+ // Gets the current segment - sub-string between previous position (after
+ // '(', ')', ',', or the beginning of the input) and the current position.
+ StringPiece segment =
+ paths.substr(previous_position, i - previous_position);
+ string current_prefix = prefix.empty() ? "" : prefix.top();
+
+ if (i < length && paths[i] == '(') {
+ // Builds a prefix and save it into the stack.
+ prefix.push(AppendPathSegmentToPrefix(current_prefix, segment));
+ } else if (!segment.empty()) {
+ // When the current charactor is ')', ',' or the current position has
+ // passed the end of the input, builds and outputs a new paths by
+ // concatenating the last prefix with the current segment.
+ RETURN_IF_ERROR(CallPathSink(
+ path_sink, AppendPathSegmentToPrefix(current_prefix, segment)));
+ }
+
+ // Removes the last prefix after seeing a ')'.
+ if (i < length && paths[i] == ')') {
+ if (prefix.empty()) {
+ return CreatePublicError(
+ util::error::INVALID_ARGUMENT,
+ StrCat("Invalid FieldMask '", paths,
+ "'. Cannot find matching '(' for all ')'."));
+ }
+ prefix.pop();
+ }
+ previous_position = i + 1;
+ }
+ if (in_map_key) {
+ return CreatePublicError(
+ util::error::INVALID_ARGUMENT,
+ StrCat("Invalid FieldMask '", paths,
+ "'. Cannot find matching ']' for all '['."));
+ }
+ if (!prefix.empty()) {
+ return CreatePublicError(
+ util::error::INVALID_ARGUMENT,
+ StrCat("Invalid FieldMask '", paths,
+ "'. Cannot find matching ')' for all '('."));
+ }
+ return util::Status::OK;
+}
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/field_mask_utility.h b/src/google/protobuf/util/internal/field_mask_utility.h
new file mode 100644
index 00000000..59f36f75
--- /dev/null
+++ b/src/google/protobuf/util/internal/field_mask_utility.h
@@ -0,0 +1,72 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// FieldMask related utility methods.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_FIELD_MASK_UTILITY_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_FIELD_MASK_UTILITY_H__
+
+#include <functional>
+#include <stack>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/status.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+typedef string (*ConverterCallback)(StringPiece);
+typedef ResultCallback1<util::Status, StringPiece>* PathSinkCallback;
+
+// Applies a 'converter' to each segment of a FieldMask path and returns the
+// result. Quoted strings in the 'path' are copied to the output as-is without
+// converting their content. Escaping is supported within quoted strings.
+// For example, "ab\"_c" will be returned as "ab\"_c" without any changes.
+string ConvertFieldMaskPath(const StringPiece path,
+ ConverterCallback converter);
+
+// Decodes a compact list of FieldMasks. For example, "a.b,a.c.d,a.c.e" will be
+// decoded into a list of field paths - "a.b", "a.c.d", "a.c.e". And the results
+// will be sent to 'path_sink', i.e. 'path_sink' will be called once per
+// resulting path.
+// Note that we also support Apiary style FieldMask form. The above example in
+// the Apiary style will look like "a.b,a.c(d,e)".
+util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
+ PathSinkCallback path_sink);
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_FIELD_MASK_UTILITY_H__
diff --git a/src/google/protobuf/util/internal/json_escaping.cc b/src/google/protobuf/util/internal/json_escaping.cc
new file mode 100644
index 00000000..5ac23421
--- /dev/null
+++ b/src/google/protobuf/util/internal/json_escaping.cc
@@ -0,0 +1,403 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/json_escaping.h>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+namespace {
+
+// Array of hex characters for conversion to hex.
+static const char kHex[] = "0123456789abcdef";
+
+// Characters 0x00 to 0x9f are very commonly used, so we provide a special
+// table lookup.
+//
+// For unicode code point ch < 0xa0:
+// kCommonEscapes[ch] is the escaped string of ch, if escaping is needed;
+// or an empty string, if escaping is not needed.
+static const char kCommonEscapes[160][7] = {
+ // C0 (ASCII and derivatives) control characters
+ "\\u0000", "\\u0001", "\\u0002", "\\u0003", // 0x00
+ "\\u0004", "\\u0005", "\\u0006", "\\u0007",
+ "\\b", "\\t", "\\n", "\\u000b",
+ "\\f", "\\r", "\\u000e", "\\u000f",
+ "\\u0010", "\\u0011", "\\u0012", "\\u0013", // 0x10
+ "\\u0014", "\\u0015", "\\u0016", "\\u0017",
+ "\\u0018", "\\u0019", "\\u001a", "\\u001b",
+ "\\u001c", "\\u001d", "\\u001e", "\\u001f",
+ // Escaping of " and \ are required by www.json.org string definition.
+ // Escaping of < and > are required for HTML security.
+ "", "", "\\\"", "", "", "", "", "", // 0x20
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", // 0x30
+ "", "", "", "", "\\u003c", "", "\\u003e", "",
+ "", "", "", "", "", "", "", "", // 0x40
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", // 0x50
+ "", "", "", "", "\\\\", "", "", "",
+ "", "", "", "", "", "", "", "", // 0x60
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", // 0x70
+ "", "", "", "", "", "", "", "\\u007f",
+ // C1 (ISO 8859 and Unicode) extended control characters
+ "\\u0080", "\\u0081", "\\u0082", "\\u0083", // 0x80
+ "\\u0084", "\\u0085", "\\u0086", "\\u0087",
+ "\\u0088", "\\u0089", "\\u008a", "\\u008b",
+ "\\u008c", "\\u008d", "\\u008e", "\\u008f",
+ "\\u0090", "\\u0091", "\\u0092", "\\u0093", // 0x90
+ "\\u0094", "\\u0095", "\\u0096", "\\u0097",
+ "\\u0098", "\\u0099", "\\u009a", "\\u009b",
+ "\\u009c", "\\u009d", "\\u009e", "\\u009f"
+};
+
+// Determines if the given char value is a unicode high-surrogate code unit.
+// Such values do not represent characters by themselves, but are used in the
+// representation of supplementary characters in the utf-16 encoding.
+inline bool IsHighSurrogate(uint16 c) {
+ // Optimized form of:
+ // return c >= kMinHighSurrogate && c <= kMaxHighSurrogate;
+ // (Reduced from 3 ALU instructions to 2 ALU instructions)
+ return (c & ~(JsonEscaping::kMaxHighSurrogate -
+ JsonEscaping::kMinHighSurrogate))
+ == JsonEscaping::kMinHighSurrogate;
+}
+
+// Determines if the given char value is a unicode low-surrogate code unit.
+// Such values do not represent characters by themselves, but are used in the
+// representation of supplementary characters in the utf-16 encoding.
+inline bool IsLowSurrogate(uint16 c) {
+ // Optimized form of:
+ // return c >= kMinLowSurrogate && c <= kMaxLowSurrogate;
+ // (Reduced from 3 ALU instructions to 2 ALU instructions)
+ return (c & ~(JsonEscaping::kMaxLowSurrogate -
+ JsonEscaping::kMinLowSurrogate))
+ == JsonEscaping::kMinLowSurrogate;
+}
+
+// Determines if the given char value is a unicode surrogate code unit (either
+// high-surrogate or low-surrogate).
+inline bool IsSurrogate(uint32 c) {
+ // Optimized form of:
+ // return c >= kMinHighSurrogate && c <= kMaxLowSurrogate;
+ // (Reduced from 3 ALU instructions to 2 ALU instructions)
+ return (c & 0xfffff800) == JsonEscaping::kMinHighSurrogate;
+}
+
+// Returns true if the given unicode code point cp is
+// in the supplementary character range.
+inline bool IsSupplementalCodePoint(uint32 cp) {
+ // Optimized form of:
+ // return kMinSupplementaryCodePoint <= cp && cp <= kMaxCodePoint;
+ // (Reduced from 3 ALU instructions to 2 ALU instructions)
+ return (cp & ~(JsonEscaping::kMinSupplementaryCodePoint - 1))
+ < JsonEscaping::kMaxCodePoint;
+}
+
+// Returns true if the given unicode code point cp is a valid
+// unicode code point (i.e. in the range 0 <= cp <= kMaxCodePoint).
+inline bool IsValidCodePoint(uint32 cp) {
+ return cp <= JsonEscaping::kMaxCodePoint;
+}
+
+// Converts the specified surrogate pair to its supplementary code point value.
+// It is the callers' responsibility to validate the specified surrogate pair.
+inline uint32 ToCodePoint(uint16 high, uint16 low) {
+ // Optimized form of:
+ // return ((high - kMinHighSurrogate) << 10)
+ // + (low - kMinLowSurrogate)
+ // + kMinSupplementaryCodePoint;
+ // (Reduced from 5 ALU instructions to 3 ALU instructions)
+ return (high << 10) + low +
+ (JsonEscaping::kMinSupplementaryCodePoint
+ - (static_cast<unsigned>(JsonEscaping::kMinHighSurrogate) << 10)
+ - JsonEscaping::kMinLowSurrogate);
+}
+
+// Returns the low surrogate for the given unicode code point. The result is
+// meaningless if the given code point is not a supplementary character.
+inline uint16 ToLowSurrogate(uint32 cp) {
+ return (cp & (JsonEscaping::kMaxLowSurrogate
+ - JsonEscaping::kMinLowSurrogate))
+ + JsonEscaping::kMinLowSurrogate;
+}
+
+// Returns the high surrogate for the given unicode code point. The result is
+// meaningless if the given code point is not a supplementary character.
+inline uint16 ToHighSurrogate(uint32 cp) {
+ return (cp >> 10) + (JsonEscaping::kMinHighSurrogate -
+ (JsonEscaping::kMinSupplementaryCodePoint >> 10));
+}
+
+// Input str is encoded in UTF-8. A unicode code point could be encoded in
+// UTF-8 using anywhere from 1 to 4 characters, and it could span multiple
+// reads of the ByteSource.
+//
+// This function reads the next unicode code point from the input (str) at
+// the given position (index), taking into account any left-over partial
+// code point from the previous iteration (cp), together with the number
+// of characters left to read to complete this code point (num_left).
+//
+// This function assumes that the input (str) is valid at the given position
+// (index). In order words, at least one character could be read successfully.
+//
+// The code point read (partial or complete) is stored in (cp). Upon return,
+// (num_left) stores the number of characters that has yet to be read in
+// order to complete the current unicode code point. If the read is complete,
+// then (num_left) is 0. Also, (num_read) is the number of characters read.
+//
+// Returns false if we encounter an invalid UTF-8 string. Returns true
+// otherwise, including the case when we reach the end of the input (str)
+// before a complete unicode code point is read.
+bool ReadCodePoint(StringPiece str, int index,
+ uint32 *cp, int* num_left, int *num_read) {
+ if (*num_left == 0) {
+ // Last read was complete. Start reading a new unicode code point.
+ *cp = str[index++];
+ *num_read = 1;
+ // The length of the code point is determined from reading the first byte.
+ //
+ // If the first byte is between:
+ // 0..0x7f: that's the value of the code point.
+ // 0x80..0xbf: <invalid>
+ // 0xc0..0xdf: 11-bit code point encoded in 2 bytes.
+ // bit 10-6, bit 5-0
+ // 0xe0..0xef: 16-bit code point encoded in 3 bytes.
+ // bit 15-12, bit 11-6, bit 5-0
+ // 0xf0..0xf7: 21-bit code point encoded in 4 bytes.
+ // bit 20-18, bit 17-12, bit 11-6, bit 5-0
+ // 0xf8..0xff: <invalid>
+ //
+ // Meaning of each bit:
+ // <msb> bit 7: 0 - single byte code point: bits 6-0 are values.
+ // 1 - multibyte code point
+ // bit 6: 0 - subsequent bytes of multibyte code point:
+ // bits 5-0 are values.
+ // 1 - first byte of multibyte code point
+ // bit 5: 0 - first byte of 2-byte code point: bits 4-0 are values.
+ // 1 - first byte of code point with >= 3 bytes.
+ // bit 4: 0 - first byte of 3-byte code point: bits 3-0 are values.
+ // 1 - first byte of code point with >= 4 bytes.
+ // bit 3: 0 - first byte of 4-byte code point: bits 2-0 are values.
+ // 1 - reserved for future expansion.
+ if (*cp <= 0x7f) {
+ return true;
+ } else if (*cp <= 0xbf) {
+ return false;
+ } else if (*cp <= 0xdf) {
+ *cp &= 0x1f;
+ *num_left = 1;
+ } else if (*cp <= 0xef) {
+ *cp &= 0x0f;
+ *num_left = 2;
+ } else if (*cp <= 0xf7) {
+ *cp &= 0x07;
+ *num_left = 3;
+ } else {
+ return false;
+ }
+ } else {
+ // Last read was partial. Initialize num_read to 0 and continue reading
+ // the last unicode code point.
+ *num_read = 0;
+ }
+ while (*num_left > 0 && index < str.size()) {
+ uint32 ch = str[index++];
+ --(*num_left);
+ ++(*num_read);
+ *cp = (*cp << 6) | (ch & 0x3f);
+ if (ch < 0x80 || ch > 0xbf) return false;
+ }
+ return *num_left > 0 || (!IsSurrogate(*cp) && IsValidCodePoint(*cp));
+}
+
+// Stores the 16-bit unicode code point as its hexadecimal digits in buffer
+// and returns a StringPiece that points to this buffer. The input buffer needs
+// to be at least 6 bytes long.
+StringPiece ToHex(uint16 cp, char* buffer) {
+ buffer[5] = kHex[cp & 0x0f];
+ cp >>= 4;
+ buffer[4] = kHex[cp & 0x0f];
+ cp >>= 4;
+ buffer[3] = kHex[cp & 0x0f];
+ cp >>= 4;
+ buffer[2] = kHex[cp & 0x0f];
+ return StringPiece(buffer, 0, 6);
+}
+
+// Stores the 32-bit unicode code point as its hexadecimal digits in buffer
+// and returns a StringPiece that points to this buffer. The input buffer needs
+// to be at least 12 bytes long.
+StringPiece ToSurrogateHex(uint32 cp, char* buffer) {
+ uint16 low = ToLowSurrogate(cp);
+ uint16 high = ToHighSurrogate(cp);
+
+ buffer[11] = kHex[low & 0x0f];
+ low >>= 4;
+ buffer[10] = kHex[low & 0x0f];
+ low >>= 4;
+ buffer[9] = kHex[low & 0x0f];
+ low >>= 4;
+ buffer[8] = kHex[low & 0x0f];
+
+ buffer[5] = kHex[high & 0x0f];
+ high >>= 4;
+ buffer[4] = kHex[high & 0x0f];
+ high >>= 4;
+ buffer[3] = kHex[high & 0x0f];
+ high >>= 4;
+ buffer[2] = kHex[high & 0x0f];
+
+ return StringPiece(buffer, 12);
+}
+
+// If the given unicode code point needs escaping, then returns the
+// escaped form. The returned StringPiece either points to statically
+// pre-allocated char[] or to the given buffer. The input buffer needs
+// to be at least 12 bytes long.
+//
+// If the given unicode code point does not need escaping, an empty
+// StringPiece is returned.
+StringPiece EscapeCodePoint(uint32 cp, char* buffer) {
+ if (cp < 0xa0) return kCommonEscapes[cp];
+ switch (cp) {
+ // These are not required by json spec
+ // but used to prevent security bugs in javascript.
+ case 0xfeff: // Zero width no-break space
+ case 0xfff9: // Interlinear annotation anchor
+ case 0xfffa: // Interlinear annotation separator
+ case 0xfffb: // Interlinear annotation terminator
+
+ case 0x00ad: // Soft-hyphen
+ case 0x06dd: // Arabic end of ayah
+ case 0x070f: // Syriac abbreviation mark
+ case 0x17b4: // Khmer vowel inherent Aq
+ case 0x17b5: // Khmer vowel inherent Aa
+ return ToHex(cp, buffer);
+
+ default:
+ if ((cp >= 0x0600 && cp <= 0x0603) || // Arabic signs
+ (cp >= 0x200b && cp <= 0x200f) || // Zero width etc.
+ (cp >= 0x2028 && cp <= 0x202e) || // Separators etc.
+ (cp >= 0x2060 && cp <= 0x2064) || // Invisible etc.
+ (cp >= 0x206a && cp <= 0x206f)) { // Shaping etc.
+ return ToHex(cp, buffer);
+ }
+
+ if (cp == 0x000e0001 || // Language tag
+ (cp >= 0x0001d173 && cp <= 0x0001d17a) || // Music formatting
+ (cp >= 0x000e0020 && cp <= 0x000e007f)) { // TAG symbols
+ return ToSurrogateHex(cp, buffer);
+ }
+ }
+ return StringPiece();
+}
+
+// Tries to escape the given code point first. If the given code point
+// does not need to be escaped, but force_output is true, then render
+// the given multi-byte code point in UTF8 in the buffer and returns it.
+StringPiece EscapeCodePoint(uint32 cp, char* buffer, bool force_output) {
+ StringPiece sp = EscapeCodePoint(cp, buffer);
+ if (force_output && sp.empty()) {
+ buffer[5] = (cp & 0x3f) | 0x80;
+ cp >>= 6;
+ if (cp <= 0x1f) {
+ buffer[4] = cp | 0xc0;
+ sp.set(buffer + 4, 2);
+ return sp;
+ }
+ buffer[4] = (cp & 0x3f) | 0x80;
+ cp >>= 6;
+ if (cp <= 0x0f) {
+ buffer[3] = cp | 0xe0;
+ sp.set(buffer + 3, 3);
+ return sp;
+ }
+ buffer[3] = (cp & 0x3f) | 0x80;
+ buffer[2] = ((cp >> 6) & 0x07) | 0xf0;
+ sp.set(buffer + 2, 4);
+ }
+ return sp;
+}
+
+} // namespace
+
+void JsonEscaping::Escape(strings::ByteSource* input,
+ strings::ByteSink* output) {
+ char buffer[12] = "\\udead\\ubee";
+ uint32 cp = 0; // Current unicode code point.
+ int num_left = 0; // Num of chars to read to complete the code point.
+ while (input->Available() > 0) {
+ StringPiece str = input->Peek();
+ StringPiece escaped;
+ int i = 0;
+ int num_read;
+ bool ok;
+ bool cp_was_split = num_left > 0;
+ // Loop until we encounter either
+ // i) a code point that needs to be escaped; or
+ // ii) a split code point is completely read; or
+ // iii) a character that is not a valid utf8; or
+ // iv) end of the StringPiece str is reached.
+ do {
+ ok = ReadCodePoint(str, i, &cp, &num_left, &num_read);
+ if (num_left > 0 || !ok) break; // case iii or iv
+ escaped = EscapeCodePoint(cp, buffer, cp_was_split);
+ if (!escaped.empty()) break; // case i or ii
+ i += num_read;
+ num_read = 0;
+ } while (i < str.length()); // case iv
+ // First copy the un-escaped prefix, if any, to the output ByteSink.
+ if (i > 0) input->CopyTo(output, i);
+ if (num_read > 0) input->Skip(num_read);
+ if (!ok) {
+ // Case iii: Report error.
+ // TODO(wpoon): Add error reporting.
+ num_left = 0;
+ } else if (num_left == 0 && !escaped.empty()) {
+ // Case i or ii: Append the escaped code point to the output ByteSink.
+ output->Append(escaped.data(), escaped.size());
+ }
+ }
+ if (num_left > 0) {
+ // Treat as case iii: report error.
+ // TODO(wpoon): Add error reporting.
+ }
+}
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/json_escaping.h b/src/google/protobuf/util/internal/json_escaping.h
new file mode 100644
index 00000000..e3e329fc
--- /dev/null
+++ b/src/google/protobuf/util/internal/json_escaping.h
@@ -0,0 +1,91 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef NET_PROTO2_UTIL_CONVERTER_STRINGS_JSON_ESCAPING_H_
+#define NET_PROTO2_UTIL_CONVERTER_STRINGS_JSON_ESCAPING_H_
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/bytestream.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+class JsonEscaping {
+ public:
+ // The minimum value of a unicode high-surrogate code unit in the utf-16
+ // encoding. A high-surrogate is also known as a leading-surrogate.
+ // See http://www.unicode.org/glossary/#high_surrogate_code_unit
+ static const uint16 kMinHighSurrogate = 0xd800;
+
+ // The maximum value of a unicide high-surrogate code unit in the utf-16
+ // encoding. A high-surrogate is also known as a leading-surrogate.
+ // See http://www.unicode.org/glossary/#high_surrogate_code_unit
+ static const uint16 kMaxHighSurrogate = 0xdbff;
+
+ // The minimum value of a unicode low-surrogate code unit in the utf-16
+ // encoding. A low-surrogate is also known as a trailing-surrogate.
+ // See http://www.unicode.org/glossary/#low_surrogate_code_unit
+ static const uint16 kMinLowSurrogate = 0xdc00;
+
+ // The maximum value of a unicode low-surrogate code unit in the utf-16
+ // encoding. A low-surrogate is also known as a trailing surrogate.
+ // See http://www.unicode.org/glossary/#low_surrogate_code_unit
+ static const uint16 kMaxLowSurrogate = 0xdfff;
+
+ // The minimum value of a unicode supplementary code point.
+ // See http://www.unicode.org/glossary/#supplementary_code_point
+ static const uint32 kMinSupplementaryCodePoint = 0x010000;
+
+ // The minimum value of a unicode code point.
+ // See http://www.unicode.org/glossary/#code_point
+ static const uint32 kMinCodePoint = 0x000000;
+
+ // The maximum value of a unicode code point.
+ // See http://www.unicode.org/glossary/#code_point
+ static const uint32 kMaxCodePoint = 0x10ffff;
+
+ JsonEscaping() {}
+ virtual ~JsonEscaping() {}
+
+ // Escape the given ByteSource to the given ByteSink.
+ static void Escape(strings::ByteSource* input, strings::ByteSink* output);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JsonEscaping);
+};
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+#endif // NET_PROTO2_UTIL_CONVERTER_STRINGS_JSON_ESCAPING_H_
+} // namespace google
diff --git a/src/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc
new file mode 100644
index 00000000..0c41515f
--- /dev/null
+++ b/src/google/protobuf/util/internal/json_objectwriter.cc
@@ -0,0 +1,175 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/json_objectwriter.h>
+
+#include <math.h>
+
+#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/util/internal/json_escaping.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+using strings::ArrayByteSource;
+
+JsonObjectWriter::~JsonObjectWriter() {
+ if (!element_->is_root()) {
+ GOOGLE_LOG(WARNING) << "JsonObjectWriter was not fully closed.";
+ }
+}
+
+JsonObjectWriter* JsonObjectWriter::StartObject(StringPiece name) {
+ WritePrefix(name);
+ WriteChar('{');
+ Push();
+ return this;
+}
+
+JsonObjectWriter* JsonObjectWriter::EndObject() {
+ Pop();
+ WriteChar('}');
+ if (element()->is_root()) NewLine();
+ return this;
+}
+
+JsonObjectWriter* JsonObjectWriter::StartList(StringPiece name) {
+ WritePrefix(name);
+ WriteChar('[');
+ Push();
+ return this;
+}
+
+JsonObjectWriter* JsonObjectWriter::EndList() {
+ Pop();
+ WriteChar(']');
+ if (element()->is_root()) NewLine();
+ return this;
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderBool(StringPiece name,
+ bool value) {
+ return RenderSimple(name, value ? "true" : "false");
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name,
+ int32 value) {
+ return RenderSimple(name, SimpleItoa(value));
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderUint32(StringPiece name,
+ uint32 value) {
+ return RenderSimple(name, SimpleItoa(value));
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name,
+ int64 value) {
+ WritePrefix(name);
+ WriteChar('"');
+ stream_->WriteString(SimpleItoa(value));
+ WriteChar('"');
+ return this;
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderUint64(StringPiece name,
+ uint64 value) {
+ WritePrefix(name);
+ WriteChar('"');
+ stream_->WriteString(SimpleItoa(value));
+ WriteChar('"');
+ return this;
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name,
+ double value) {
+ if (isfinite(value)) return RenderSimple(name, SimpleDtoa(value));
+
+ // Render quoted with NaN/Infinity-aware DoubleAsString.
+ return RenderString(name, DoubleAsString(value));
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name,
+ float value) {
+ if (isfinite(value)) return RenderSimple(name, SimpleFtoa(value));
+
+ // Render quoted with NaN/Infinity-aware FloatAsString.
+ return RenderString(name, FloatAsString(value));
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderString(StringPiece name,
+ StringPiece value) {
+ WritePrefix(name);
+ WriteChar('"');
+ ArrayByteSource source(value);
+ JsonEscaping::Escape(&source, &sink_);
+ WriteChar('"');
+ return this;
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderBytes(StringPiece name,
+ StringPiece value) {
+ WritePrefix(name);
+ string base64;
+ WebSafeBase64EscapeWithPadding(value, &base64);
+ WriteChar('"');
+ // TODO(wpoon): Consider a ByteSink solution that writes the base64 bytes
+ // directly to the stream, rather than first putting them
+ // into a string and then writing them to the stream.
+ stream_->WriteRaw(base64.data(), base64.size());
+ WriteChar('"');
+ return this;
+}
+
+JsonObjectWriter* JsonObjectWriter::RenderNull(StringPiece name) {
+ return RenderSimple(name, "null");
+}
+
+void JsonObjectWriter::WritePrefix(StringPiece name) {
+ bool not_first = !element()->is_first();
+ if (not_first) WriteChar(',');
+ if (not_first || !element()->is_root()) NewLine();
+ if (!name.empty()) {
+ WriteChar('"');
+ ArrayByteSource source(name);
+ JsonEscaping::Escape(&source, &sink_);
+ stream_->WriteString("\":");
+ if (!indent_string_.empty()) WriteChar(' ');
+ }
+}
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/json_objectwriter.h b/src/google/protobuf/util/internal/json_objectwriter.h
new file mode 100644
index 00000000..761a0a10
--- /dev/null
+++ b/src/google/protobuf/util/internal/json_objectwriter.h
@@ -0,0 +1,206 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/util/internal/structured_objectwriter.h>
+#include <google/protobuf/stubs/bytestream.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// An ObjectWriter implementation that outputs JSON. This ObjectWriter
+// supports writing a compact form or a pretty printed form.
+//
+// Sample usage:
+// string output;
+// StringOutputStream* str_stream = new StringOutputStream(&output);
+// CodedOutputStream* out_stream = new CodedOutputStream(str_stream);
+// JsonObjectWriter* ow = new JsonObjectWriter(" ", out_stream);
+// ow->StartObject("")
+// ->RenderString("name", "value")
+// ->RenderString("emptystring", string())
+// ->StartObject("nested")
+// ->RenderInt64("light", 299792458);
+// ->RenderDouble("pi", 3.141592653589793);
+// ->EndObject()
+// ->StartList("empty")
+// ->EndList()
+// ->EndObject();
+//
+// And then the output string would become:
+// {
+// "name": "value",
+// "emptystring": "",
+// "nested": {
+// "light": "299792458",
+// "pi": 3.141592653589793
+// },
+// "empty": []
+// }
+//
+// JsonObjectWriter does not validate if calls actually result in valid JSON.
+// For example, passing an empty name when one would be required won't result
+// in an error, just an invalid output.
+//
+// Note that all int64 and uint64 are rendered as strings instead of numbers.
+// This is because JavaScript parses numbers as 64-bit float thus int64 and
+// uint64 would lose precision if rendered as numbers.
+//
+// JsonObjectWriter is thread-unsafe.
+class LIBPROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter {
+ public:
+ JsonObjectWriter(StringPiece indent_string,
+ google::protobuf::io::CodedOutputStream* out)
+ : element_(new Element(NULL)),
+ stream_(out), sink_(out),
+ indent_string_(indent_string.ToString()) {
+ }
+ virtual ~JsonObjectWriter();
+
+ // ObjectWriter methods.
+ virtual JsonObjectWriter* StartObject(StringPiece name);
+ virtual JsonObjectWriter* EndObject();
+ virtual JsonObjectWriter* StartList(StringPiece name);
+ virtual JsonObjectWriter* EndList();
+ virtual JsonObjectWriter* RenderBool(StringPiece name, bool value);
+ virtual JsonObjectWriter* RenderInt32(StringPiece name, int32 value);
+ virtual JsonObjectWriter* RenderUint32(StringPiece name, uint32 value);
+ virtual JsonObjectWriter* RenderInt64(StringPiece name, int64 value);
+ virtual JsonObjectWriter* RenderUint64(StringPiece name, uint64 value);
+ virtual JsonObjectWriter* RenderDouble(StringPiece name, double value);
+ virtual JsonObjectWriter* RenderFloat(StringPiece name, float value);
+ virtual JsonObjectWriter* RenderString(StringPiece name, StringPiece value);
+ virtual JsonObjectWriter* RenderBytes(StringPiece name, StringPiece value);
+ virtual JsonObjectWriter* RenderNull(StringPiece name);
+
+ protected:
+ class LIBPROTOBUF_EXPORT Element : public BaseElement {
+ public:
+ explicit Element(Element* parent) : BaseElement(parent), is_first_(true) {}
+
+ // Called before each field of the Element is to be processed.
+ // Returns true if this is the first call (processing the first field).
+ bool is_first() {
+ if (is_first_) {
+ is_first_ = false;
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ bool is_first_;
+
+ GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(Element);
+ };
+
+ virtual Element* element() { return element_.get(); }
+
+ private:
+ class LIBPROTOBUF_EXPORT ByteSinkWrapper : public strings::ByteSink {
+ public:
+ explicit ByteSinkWrapper(google::protobuf::io::CodedOutputStream* stream)
+ : stream_(stream) {}
+ virtual ~ByteSinkWrapper() {}
+
+ // ByteSink methods.
+ virtual void Append(const char* bytes, size_t n) {
+ stream_->WriteRaw(bytes, n);
+ }
+
+ private:
+ google::protobuf::io::CodedOutputStream* stream_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSinkWrapper);
+ };
+
+ // Renders a simple value as a string. By default all non-string Render
+ // methods convert their argument to a string and call this method. This
+ // method can then be used to render the simple value without escaping it.
+ JsonObjectWriter* RenderSimple(StringPiece name, const string& value) {
+ WritePrefix(name);
+ stream_->WriteString(value);
+ return this;
+ }
+
+ // Pushes a new element to the stack.
+ void Push() { element_.reset(new Element(element_.release())); }
+
+ // Pops an element off of the stack and deletes the popped element.
+ void Pop() {
+ bool needs_newline = !element_->is_first();
+ element_.reset(element_->pop<Element>());
+ if (needs_newline) NewLine();
+ }
+
+ // If pretty printing is enabled, this will write a newline to the output,
+ // followed by optional indentation. Otherwise this method is a noop.
+ void NewLine() {
+ if (!indent_string_.empty()) {
+ WriteChar('\n');
+ for (int i = 0; i < element()->level(); i++) {
+ stream_->WriteString(indent_string_);
+ }
+ }
+ }
+
+ // Writes a prefix. This will write out any pretty printing and
+ // commas that are required, followed by the name and a ':' if
+ // the name is not null.
+ void WritePrefix(StringPiece name);
+
+ // Writes an individual character to the output.
+ void WriteChar(const char c) { stream_->WriteRaw(&c, sizeof(c)); }
+
+ google::protobuf::scoped_ptr<Element> element_;
+ google::protobuf::io::CodedOutputStream* stream_;
+ ByteSinkWrapper sink_;
+ const string indent_string_;
+
+ GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonObjectWriter);
+};
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__
diff --git a/src/google/protobuf/util/internal/json_objectwriter_test.cc b/src/google/protobuf/util/internal/json_objectwriter_test.cc
new file mode 100644
index 00000000..df9a133e
--- /dev/null
+++ b/src/google/protobuf/util/internal/json_objectwriter_test.cc
@@ -0,0 +1,285 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/json_objectwriter.h>
+
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/util/internal/utility.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+using google::protobuf::io::CodedOutputStream;
+using google::protobuf::io::StringOutputStream;
+
+class JsonObjectWriterTest : public ::testing::Test {
+ protected:
+ JsonObjectWriterTest()
+ : str_stream_(new StringOutputStream(&output_)),
+ out_stream_(new CodedOutputStream(str_stream_)),
+ ow_(NULL) {}
+
+ virtual ~JsonObjectWriterTest() {
+ delete ow_;
+ delete out_stream_;
+ delete str_stream_;
+ }
+
+ string output_;
+ StringOutputStream* const str_stream_;
+ CodedOutputStream* const out_stream_;
+ ObjectWriter* ow_;
+};
+
+TEST_F(JsonObjectWriterTest, EmptyRootObject) {
+ ow_ = new JsonObjectWriter("", out_stream_);
+ ow_->StartObject("")->EndObject();
+ EXPECT_EQ("{}", output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, EmptyObject) {
+ ow_ = new JsonObjectWriter("", out_stream_);
+ ow_->StartObject("")
+ ->RenderString("test", "value")
+ ->StartObject("empty")
+ ->EndObject()
+ ->EndObject();
+ EXPECT_EQ("{\"test\":\"value\",\"empty\":{}}",
+ output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, EmptyRootList) {
+ ow_ = new JsonObjectWriter("", out_stream_);
+ ow_->StartList("")->EndList();
+ EXPECT_EQ("[]", output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, EmptyList) {
+ ow_ = new JsonObjectWriter("", out_stream_);
+ ow_->StartObject("")
+ ->RenderString("test", "value")
+ ->StartList("empty")
+ ->EndList()
+ ->EndObject();
+ EXPECT_EQ("{\"test\":\"value\",\"empty\":[]}",
+ output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, ObjectInObject) {
+ ow_ = new JsonObjectWriter("", out_stream_);
+ ow_->StartObject("")
+ ->StartObject("nested")
+ ->RenderString("field", "value")
+ ->EndObject()
+ ->EndObject();
+ EXPECT_EQ("{\"nested\":{\"field\":\"value\"}}",
+ output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, ListInObject) {
+ ow_ = new JsonObjectWriter("", out_stream_);
+ ow_->StartObject("")
+ ->StartList("nested")
+ ->RenderString("", "value")
+ ->EndList()
+ ->EndObject();
+ EXPECT_EQ("{\"nested\":[\"value\"]}",
+ output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, ObjectInList) {
+ ow_ = new JsonObjectWriter("", out_stream_);
+ ow_->StartList("")
+ ->StartObject("")
+ ->RenderString("field", "value")
+ ->EndObject()
+ ->EndList();
+ EXPECT_EQ("[{\"field\":\"value\"}]",
+ output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, ListInList) {
+ ow_ = new JsonObjectWriter("", out_stream_);
+ ow_->StartList("")
+ ->StartList("")
+ ->RenderString("", "value")
+ ->EndList()
+ ->EndList();
+ EXPECT_EQ("[[\"value\"]]", output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, RenderPrimitives) {
+ ow_ = new JsonObjectWriter("", out_stream_);
+ ow_->StartObject("")
+ ->RenderBool("bool", true)
+ ->RenderDouble("double", std::numeric_limits<double>::max())
+ ->RenderFloat("float", std::numeric_limits<float>::max())
+ ->RenderInt32("int", std::numeric_limits<int32>::min())
+ ->RenderInt64("long", std::numeric_limits<int64>::min())
+ ->RenderBytes("bytes", "abracadabra")
+ ->RenderString("string", "string")
+ ->RenderBytes("emptybytes", "")
+ ->RenderString("emptystring", string())
+ ->EndObject();
+ EXPECT_EQ(
+ "{\"bool\":true,"
+ "\"double\":" + ValueAsString<double>(1.7976931348623157e+308) + ","
+ "\"float\":" + ValueAsString<float>(3.4028235e+38) + ","
+ "\"int\":-2147483648,"
+ "\"long\":\"-9223372036854775808\","
+ "\"bytes\":\"YWJyYWNhZGFicmE=\","
+ "\"string\":\"string\","
+ "\"emptybytes\":\"\","
+ "\"emptystring\":\"\"}",
+ output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, BytesEncodesAsWebSafeBase64) {
+ string s;
+ s.push_back('\377');
+ s.push_back('\357');
+ ow_ = new JsonObjectWriter("", out_stream_);
+ ow_->StartObject("")->RenderBytes("bytes", s)->EndObject();
+ // Non-web-safe would encode this as "/+8="
+ EXPECT_EQ("{\"bytes\":\"_-8=\"}",
+ output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, PrettyPrintList) {
+ ow_ = new JsonObjectWriter(" ", out_stream_);
+ ow_->StartObject("")
+ ->StartList("items")
+ ->RenderString("", "item1")
+ ->RenderString("", "item2")
+ ->RenderString("", "item3")
+ ->EndList()
+ ->StartList("empty")
+ ->EndList()
+ ->EndObject();
+ EXPECT_EQ(
+ "{\n"
+ " \"items\": [\n"
+ " \"item1\",\n"
+ " \"item2\",\n"
+ " \"item3\"\n"
+ " ],\n"
+ " \"empty\": []\n"
+ "}\n",
+ output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, PrettyPrintObject) {
+ ow_ = new JsonObjectWriter(" ", out_stream_);
+ ow_->StartObject("")
+ ->StartObject("items")
+ ->RenderString("key1", "item1")
+ ->RenderString("key2", "item2")
+ ->RenderString("key3", "item3")
+ ->EndObject()
+ ->StartObject("empty")
+ ->EndObject()
+ ->EndObject();
+ EXPECT_EQ(
+ "{\n"
+ " \"items\": {\n"
+ " \"key1\": \"item1\",\n"
+ " \"key2\": \"item2\",\n"
+ " \"key3\": \"item3\"\n"
+ " },\n"
+ " \"empty\": {}\n"
+ "}\n",
+ output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, PrettyPrintEmptyObjectInEmptyList) {
+ ow_ = new JsonObjectWriter(" ", out_stream_);
+ ow_->StartObject("")
+ ->StartList("list")
+ ->StartObject("")
+ ->EndObject()
+ ->EndList()
+ ->EndObject();
+ EXPECT_EQ(
+ "{\n"
+ " \"list\": [\n"
+ " {}\n"
+ " ]\n"
+ "}\n",
+ output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, PrettyPrintDoubleIndent) {
+ ow_ = new JsonObjectWriter(" ", out_stream_);
+ ow_->StartObject("")
+ ->RenderBool("bool", true)
+ ->RenderInt32("int", 42)
+ ->EndObject();
+ EXPECT_EQ(
+ "{\n"
+ " \"bool\": true,\n"
+ " \"int\": 42\n"
+ "}\n",
+ output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, StringsEscapedAndEnclosedInDoubleQuotes) {
+ ow_ = new JsonObjectWriter("", out_stream_);
+ ow_->StartObject("")->RenderString("string", "'<>&amp;\\\"\r\n")->EndObject();
+ EXPECT_EQ("{\"string\":\"'\\u003c\\u003e&amp;\\\\\\\"\\r\\n\"}",
+ output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, Stringification) {
+ ow_ = new JsonObjectWriter("", out_stream_);
+ ow_->StartObject("")
+ ->RenderDouble("double_nan", std::numeric_limits<double>::quiet_NaN())
+ ->RenderFloat("float_nan", std::numeric_limits<float>::quiet_NaN())
+ ->RenderDouble("double_pos", std::numeric_limits<double>::infinity())
+ ->RenderFloat("float_pos", std::numeric_limits<float>::infinity())
+ ->RenderDouble("double_neg", -std::numeric_limits<double>::infinity())
+ ->RenderFloat("float_neg", -std::numeric_limits<float>::infinity())
+ ->EndObject();
+ EXPECT_EQ(
+ "{\"double_nan\":\"NaN\","
+ "\"float_nan\":\"NaN\","
+ "\"double_pos\":\"Infinity\","
+ "\"float_pos\":\"Infinity\","
+ "\"double_neg\":\"-Infinity\","
+ "\"float_neg\":\"-Infinity\"}",
+ output_.substr(0, out_stream_->ByteCount()));
+}
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc
new file mode 100644
index 00000000..d439a221
--- /dev/null
+++ b/src/google/protobuf/util/internal/json_stream_parser.cc
@@ -0,0 +1,740 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/json_stream_parser.h>
+
+#include <algorithm>
+#include <cctype>
+#include <cerrno>
+#include <cstdlib>
+#include <cstring>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/util/internal/object_writer.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+// Allow these symbols to be referenced as util::Status, util::error::* in
+// this file.
+using util::Status;
+namespace error {
+using util::error::INTERNAL;
+using util::error::INVALID_ARGUMENT;
+} // namespace error
+
+namespace converter {
+
+// Number of digits in a unicode escape sequence (/uXXXX)
+static const int kUnicodeEscapedLength = 6;
+
+// Length of the true, false, and null literals.
+static const int true_len = strlen("true");
+static const int false_len = strlen("false");
+static const int null_len = strlen("null");
+
+inline bool IsLetter(char c) {
+ return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || (c == '_') ||
+ (c == '$');
+}
+
+inline bool IsAlphanumeric(char c) {
+ return IsLetter(c) || ('0' <= c && c <= '9');
+}
+
+static bool ConsumeKey(StringPiece* input, StringPiece* key) {
+ if (input->empty() || !IsLetter((*input)[0])) return false;
+ int len = 1;
+ for (; len < input->size(); ++len) {
+ if (!IsAlphanumeric((*input)[len])) {
+ break;
+ }
+ }
+ *key = StringPiece(input->data(), len);
+ *input = StringPiece(input->data() + len, input->size() - len);
+ return true;
+}
+
+static bool MatchKey(StringPiece input) {
+ return !input.empty() && IsLetter(input[0]);
+}
+
+JsonStreamParser::JsonStreamParser(ObjectWriter* ow)
+ : ow_(ow),
+ stack_(),
+ leftover_(),
+ json_(),
+ p_(),
+ key_(),
+ key_storage_(),
+ finishing_(false),
+ parsed_(),
+ parsed_storage_(),
+ string_open_(0),
+ utf8_storage_(),
+ utf8_length_(0) {
+ // Initialize the stack with a single value to be parsed.
+ stack_.push(VALUE);
+}
+
+JsonStreamParser::~JsonStreamParser() {}
+
+util::Status JsonStreamParser::Parse(StringPiece json) {
+ return ParseChunk(json);
+}
+
+util::Status JsonStreamParser::FinishParse() {
+ // If we do not expect anything and there is nothing left to parse we're all
+ // done.
+ if (stack_.empty() && leftover_.empty()) {
+ return util::Status::OK;
+ }
+ // Parse the remainder in finishing mode, which reports errors for things like
+ // unterminated strings or unknown tokens that would normally be retried.
+ p_ = json_ = StringPiece(leftover_);
+ finishing_ = true;
+ util::Status result = RunParser();
+ if (result.ok()) {
+ SkipWhitespace();
+ if (!p_.empty()) {
+ result = ReportFailure("Parsing terminated before end of input.");
+ }
+ }
+ return result;
+}
+
+util::Status JsonStreamParser::ParseChunk(StringPiece chunk) {
+ // If we have leftovers from a previous chunk, append the new chunk to it and
+ // create a new StringPiece pointing at the string's data. This could be
+ // large but we rely on the chunks to be small, assuming they are fragments
+ // of a Cord.
+ if (!leftover_.empty()) {
+ chunk.AppendToString(&leftover_);
+ p_ = json_ = StringPiece(leftover_);
+ } else {
+ p_ = json_ = chunk;
+ }
+
+ finishing_ = false;
+ util::Status result = RunParser();
+ if (!result.ok()) return result;
+
+ SkipWhitespace();
+ if (p_.empty()) {
+ // If we parsed everything we had, clear the leftover.
+ leftover_.clear();
+ } else {
+ // If we do not expect anything i.e. stack is empty, and we have non-empty
+ // string left to parse, we report an error.
+ if (stack_.empty()) {
+ return ReportFailure("Parsing terminated before end of input.");
+ }
+ // If we expect future data i.e. stack is non-empty, and we have some
+ // unparsed data left, we save it for later parse.
+ leftover_ = p_.ToString();
+ }
+ return util::Status::OK;
+}
+
+util::Status JsonStreamParser::RunParser() {
+ while (!stack_.empty()) {
+ ParseType type = stack_.top();
+ TokenType t = (string_open_ == 0) ? GetNextTokenType() : BEGIN_STRING;
+ stack_.pop();
+ util::Status result;
+ switch (type) {
+ case VALUE:
+ result = ParseValue(t);
+ break;
+
+ case OBJ_MID:
+ result = ParseObjectMid(t);
+ break;
+
+ case ENTRY:
+ result = ParseEntry(t);
+ break;
+
+ case ENTRY_MID:
+ result = ParseEntryMid(t);
+ break;
+
+ case ARRAY_VALUE:
+ result = ParseArrayValue(t);
+ break;
+
+ case ARRAY_MID:
+ result = ParseArrayMid(t);
+ break;
+
+ default:
+ result = util::Status(util::error::INTERNAL,
+ StrCat("Unknown parse type: ", type));
+ break;
+ }
+ if (!result.ok()) {
+ // If we were cancelled, save our state and try again later.
+ if (!finishing_ && result == util::Status::CANCELLED) {
+ stack_.push(type);
+ // If we have a key we still need to render, make sure to save off the
+ // contents in our own storage.
+ if (!key_.empty() && key_storage_.empty()) {
+ key_.AppendToString(&key_storage_);
+ key_ = StringPiece(key_storage_);
+ }
+ result = util::Status::OK;
+ }
+ return result;
+ }
+ }
+ return util::Status::OK;
+}
+
+util::Status JsonStreamParser::ParseValue(TokenType type) {
+ switch (type) {
+ case BEGIN_OBJECT:
+ return HandleBeginObject();
+ case BEGIN_ARRAY:
+ return HandleBeginArray();
+ case BEGIN_STRING:
+ return ParseString();
+ case BEGIN_NUMBER:
+ return ParseNumber();
+ case BEGIN_TRUE:
+ return ParseTrue();
+ case BEGIN_FALSE:
+ return ParseFalse();
+ case BEGIN_NULL:
+ return ParseNull();
+ case UNKNOWN:
+ return ReportUnknown("Expected a value.");
+ default: {
+ // Special case for having been cut off while parsing, wait for more data.
+ // This handles things like 'fals' being at the end of the string, we
+ // don't know if the next char would be e, completing it, or something
+ // else, making it invalid.
+ if (!finishing_ && p_.length() < false_len) {
+ return util::Status::CANCELLED;
+ }
+ return ReportFailure("Unexpected token.");
+ }
+ }
+}
+
+util::Status JsonStreamParser::ParseString() {
+ util::Status result = ParseStringHelper();
+ if (result.ok()) {
+ ow_->RenderString(key_, parsed_);
+ key_.clear();
+ parsed_.clear();
+ parsed_storage_.clear();
+ }
+ return result;
+}
+
+util::Status JsonStreamParser::ParseStringHelper() {
+ // If we haven't seen the start quote, grab it and remember it for later.
+ if (string_open_ == 0) {
+ string_open_ = *p_.data();
+ GOOGLE_DCHECK(string_open_ == '\"' || string_open_ == '\'');
+ Advance();
+ }
+ // Track where we last copied data from so we can minimize copying.
+ const char* last = p_.data();
+ while (!p_.empty()) {
+ const char* data = p_.data();
+ if (*data == '\\') {
+ // We're about to handle an escape, copy all bytes from last to data.
+ if (last < data) {
+ parsed_storage_.append(last, data - last);
+ last = data;
+ }
+ // If we ran out of string after the \, cancel or report an error
+ // depending on if we expect more data later.
+ if (p_.length() == 1) {
+ if (!finishing_) {
+ return util::Status::CANCELLED;
+ }
+ return ReportFailure("Closing quote expected in string.");
+ }
+ // Parse a unicode escape if we found \u in the string.
+ if (data[1] == 'u') {
+ util::Status result = ParseUnicodeEscape();
+ if (!result.ok()) {
+ return result;
+ }
+ // Move last pointer past the unicode escape and continue.
+ last = p_.data();
+ continue;
+ }
+ // Handle the standard set of backslash-escaped characters.
+ switch (data[1]) {
+ case 'b':
+ parsed_storage_.push_back('\b');
+ break;
+ case 'f':
+ parsed_storage_.push_back('\f');
+ break;
+ case 'n':
+ parsed_storage_.push_back('\n');
+ break;
+ case 'r':
+ parsed_storage_.push_back('\r');
+ break;
+ case 't':
+ parsed_storage_.push_back('\t');
+ break;
+ case 'v':
+ parsed_storage_.push_back('\v');
+ break;
+ default:
+ parsed_storage_.push_back(data[1]);
+ }
+ // We handled two characters, so advance past them and continue.
+ p_.remove_prefix(2);
+ last = p_.data();
+ continue;
+ }
+ // If we found the closing quote note it, advance past it, and return.
+ if (*data == string_open_) {
+ // If we didn't copy anything, reuse the input buffer.
+ if (parsed_storage_.empty()) {
+ parsed_ = StringPiece(last, data - last);
+ } else {
+ if (last < data) {
+ parsed_storage_.append(last, data - last);
+ last = data;
+ }
+ parsed_ = StringPiece(parsed_storage_);
+ }
+ // Clear the quote char so next time we try to parse a string we'll
+ // start fresh.
+ string_open_ = 0;
+ Advance();
+ return util::Status::OK;
+ }
+ // Normal character, just advance past it.
+ Advance();
+ }
+ // If we ran out of characters, copy over what we have so far.
+ if (last < p_.data()) {
+ parsed_storage_.append(last, p_.data() - last);
+ }
+ // If we didn't find the closing quote but we expect more data, cancel for now
+ if (!finishing_) {
+ return util::Status::CANCELLED;
+ }
+ // End of string reached without a closing quote, report an error.
+ string_open_ = 0;
+ return ReportFailure("Closing quote expected in string.");
+}
+
+// Converts a unicode escaped character to a decimal value stored in a char32
+// for use in UTF8 encoding utility. We assume that str begins with \uhhhh and
+// convert that from the hex number to a decimal value.
+//
+// There are some security exploits with UTF-8 that we should be careful of:
+// - http://www.unicode.org/reports/tr36/#UTF-8_Exploit
+// - http://sites/intl-eng/design-guide/core-application
+util::Status JsonStreamParser::ParseUnicodeEscape() {
+ if (p_.length() < kUnicodeEscapedLength) {
+ if (!finishing_) {
+ return util::Status::CANCELLED;
+ }
+ return ReportFailure("Illegal hex string.");
+ }
+ GOOGLE_DCHECK_EQ('\\', p_.data()[0]);
+ GOOGLE_DCHECK_EQ('u', p_.data()[1]);
+ uint32 code = 0;
+ for (int i = 2; i < kUnicodeEscapedLength; ++i) {
+ if (!isxdigit(p_.data()[i])) {
+ return ReportFailure("Invalid escape sequence.");
+ }
+ code = (code << 4) + hex_digit_to_int(p_.data()[i]);
+ }
+ char buf[UTFmax];
+ int len = EncodeAsUTF8Char(code, buf);
+ // Advance past the unicode escape.
+ p_.remove_prefix(kUnicodeEscapedLength);
+ parsed_storage_.append(buf, len);
+ return util::Status::OK;
+}
+
+util::Status JsonStreamParser::ParseNumber() {
+ NumberResult number;
+ util::Status result = ParseNumberHelper(&number);
+ if (result.ok()) {
+ switch (number.type) {
+ case NumberResult::DOUBLE:
+ ow_->RenderDouble(key_, number.double_val);
+ key_.clear();
+ break;
+
+ case NumberResult::INT:
+ ow_->RenderInt64(key_, number.int_val);
+ key_.clear();
+ break;
+
+ case NumberResult::UINT:
+ ow_->RenderUint64(key_, number.uint_val);
+ key_.clear();
+ break;
+
+ default:
+ return ReportFailure("Unable to parse number.");
+ }
+ }
+ return result;
+}
+
+util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) {
+ const char* data = p_.data();
+ int length = p_.length();
+
+ // Look for the first non-numeric character, or the end of the string.
+ int index = 0;
+ bool floating = false;
+ bool negative = data[index] == '-';
+ // Find the first character that cannot be part of the number. Along the way
+ // detect if the number needs to be parsed as a double.
+ // Note that this restricts numbers to the JSON specification, so for example
+ // we do not support hex or octal notations.
+ for (; index < length; ++index) {
+ char c = data[index];
+ if (isdigit(c)) continue;
+ if (c == '.' || c == 'e' || c == 'E') {
+ floating = true;
+ continue;
+ }
+ if (c == '+' || c == '-') continue;
+ // Not a valid number character, break out.
+ break;
+ }
+
+ // If the entire input is a valid number, and we may have more content in the
+ // future, we abort for now and resume when we know more.
+ if (index == length && !finishing_) {
+ return util::Status::CANCELLED;
+ }
+
+ // Create a string containing just the number, so we can use safe_strtoX
+ string number = p_.substr(0, index).ToString();
+
+ // Floating point number, parse as a double.
+ if (floating) {
+ if (!safe_strtod(number, &result->double_val)) {
+ return ReportFailure("Unable to parse number.");
+ }
+ result->type = NumberResult::DOUBLE;
+ p_.remove_prefix(index);
+ return util::Status::OK;
+ }
+
+ // Positive non-floating point number, parse as a uint64.
+ if (!negative) {
+ if (!safe_strtou64(number, &result->uint_val)) {
+ return ReportFailure("Unable to parse number.");
+ }
+ result->type = NumberResult::UINT;
+ p_.remove_prefix(index);
+ return util::Status::OK;
+ }
+
+ // Negative non-floating point number, parse as an int64.
+ if (!safe_strto64(number, &result->int_val)) {
+ return ReportFailure("Unable to parse number.");
+ }
+ result->type = NumberResult::INT;
+ p_.remove_prefix(index);
+ return util::Status::OK;
+}
+
+util::Status JsonStreamParser::HandleBeginObject() {
+ GOOGLE_DCHECK_EQ('{', *p_.data());
+ Advance();
+ ow_->StartObject(key_);
+ key_.clear();
+ stack_.push(ENTRY);
+ return util::Status::OK;
+}
+
+util::Status JsonStreamParser::ParseObjectMid(TokenType type) {
+ if (type == UNKNOWN) {
+ return ReportUnknown("Expected , or } after key:value pair.");
+ }
+
+ // Object is complete, advance past the comma and render the EndObject.
+ if (type == END_OBJECT) {
+ Advance();
+ ow_->EndObject();
+ return util::Status::OK;
+ }
+ // Found a comma, advance past it and get ready for an entry.
+ if (type == VALUE_SEPARATOR) {
+ Advance();
+ stack_.push(ENTRY);
+ return util::Status::OK;
+ }
+ // Illegal token after key:value pair.
+ return ReportFailure("Expected , or } after key:value pair.");
+}
+
+util::Status JsonStreamParser::ParseEntry(TokenType type) {
+ if (type == UNKNOWN) {
+ return ReportUnknown("Expected an object key or }.");
+ }
+
+ // Close the object and return. This allows for trailing commas.
+ if (type == END_OBJECT) {
+ ow_->EndObject();
+ Advance();
+ return util::Status::OK;
+ }
+
+ util::Status result;
+ if (type == BEGIN_STRING) {
+ // Key is a string (standard JSON), parse it and store the string.
+ result = ParseStringHelper();
+ if (result.ok()) {
+ key_storage_.clear();
+ if (!parsed_storage_.empty()) {
+ parsed_storage_.swap(key_storage_);
+ key_ = StringPiece(key_storage_);
+ } else {
+ key_ = parsed_;
+ }
+ parsed_.clear();
+ }
+ } else if (type == BEGIN_KEY) {
+ // Key is a bare key (back compat), create a StringPiece pointing to it.
+ result = ParseKey();
+ } else {
+ // Unknown key type, report an error.
+ result = ReportFailure("Expected an object key or }.");
+ }
+ // On success we next expect an entry mid ':' then an object mid ',' or '}'
+ if (result.ok()) {
+ stack_.push(OBJ_MID);
+ stack_.push(ENTRY_MID);
+ }
+ return result;
+}
+
+util::Status JsonStreamParser::ParseEntryMid(TokenType type) {
+ if (type == UNKNOWN) {
+ return ReportUnknown("Expected : between key:value pair.");
+ }
+ if (type == ENTRY_SEPARATOR) {
+ Advance();
+ stack_.push(VALUE);
+ return util::Status::OK;
+ }
+ return ReportFailure("Expected : between key:value pair.");
+}
+
+util::Status JsonStreamParser::HandleBeginArray() {
+ GOOGLE_DCHECK_EQ('[', *p_.data());
+ Advance();
+ ow_->StartList(key_);
+ key_.clear();
+ stack_.push(ARRAY_VALUE);
+ return util::Status::OK;
+}
+
+util::Status JsonStreamParser::ParseArrayValue(TokenType type) {
+ if (type == UNKNOWN) {
+ return ReportUnknown("Expected a value or ] within an array.");
+ }
+
+ if (type == END_ARRAY) {
+ ow_->EndList();
+ Advance();
+ return util::Status::OK;
+ }
+
+ // The ParseValue call may push something onto the stack so we need to make
+ // sure an ARRAY_MID is after it, so we push it on now.
+ stack_.push(ARRAY_MID);
+ util::Status result = ParseValue(type);
+ if (result == util::Status::CANCELLED) {
+ // If we were cancelled, pop back off the ARRAY_MID so we don't try to
+ // push it on again when we try over.
+ stack_.pop();
+ }
+ return result;
+}
+
+util::Status JsonStreamParser::ParseArrayMid(TokenType type) {
+ if (type == UNKNOWN) {
+ return ReportUnknown("Expected , or ] after array value.");
+ }
+
+ if (type == END_ARRAY) {
+ ow_->EndList();
+ Advance();
+ return util::Status::OK;
+ }
+
+ // Found a comma, advance past it and expect an array value next.
+ if (type == VALUE_SEPARATOR) {
+ Advance();
+ stack_.push(ARRAY_VALUE);
+ return util::Status::OK;
+ }
+ // Illegal token after array value.
+ return ReportFailure("Expected , or ] after array value.");
+}
+
+util::Status JsonStreamParser::ParseTrue() {
+ ow_->RenderBool(key_, true);
+ key_.clear();
+ p_.remove_prefix(true_len);
+ return util::Status::OK;
+}
+
+util::Status JsonStreamParser::ParseFalse() {
+ ow_->RenderBool(key_, false);
+ key_.clear();
+ p_.remove_prefix(false_len);
+ return util::Status::OK;
+}
+
+util::Status JsonStreamParser::ParseNull() {
+ ow_->RenderNull(key_);
+ key_.clear();
+ p_.remove_prefix(null_len);
+ return util::Status::OK;
+}
+
+util::Status JsonStreamParser::ReportFailure(StringPiece message) {
+ static const int kContextLength = 20;
+ const char* p_start = p_.data();
+ const char* json_start = json_.data();
+ const char* begin = max(p_start - kContextLength, json_start);
+ const char* end = min(p_start + kContextLength, json_start + json_.size());
+ StringPiece segment(begin, end - begin);
+ string location(p_start - begin, ' ');
+ location.push_back('^');
+ return util::Status(util::error::INVALID_ARGUMENT,
+ StrCat(message, "\n", segment, "\n", location));
+}
+
+util::Status JsonStreamParser::ReportUnknown(StringPiece message) {
+ // If we aren't finishing the parse, cancel parsing and try later.
+ if (!finishing_) {
+ return util::Status::CANCELLED;
+ }
+ if (p_.empty()) {
+ return ReportFailure(StrCat("Unexpected end of string. ", message));
+ }
+ return ReportFailure(message);
+}
+
+void JsonStreamParser::SkipWhitespace() {
+ while (!p_.empty() && ascii_isspace(*p_.data())) {
+ Advance();
+ }
+}
+
+void JsonStreamParser::Advance() {
+ // Advance by moving one UTF8 character while making sure we don't go beyond
+ // the length of StringPiece.
+ p_.remove_prefix(
+ min<int>(p_.length(), UTF8FirstLetterNumBytes(p_.data(), p_.length())));
+}
+
+util::Status JsonStreamParser::ParseKey() {
+ StringPiece original = p_;
+ if (!ConsumeKey(&p_, &key_)) {
+ return ReportFailure("Invalid key or variable name.");
+ }
+ // If we consumed everything but expect more data, reset p_ and cancel since
+ // we can't know if the key was complete or not.
+ if (!finishing_ && p_.empty()) {
+ p_ = original;
+ return util::Status::CANCELLED;
+ }
+ // Since we aren't using the key storage, clear it out.
+ key_storage_.clear();
+ return util::Status::OK;
+}
+
+JsonStreamParser::TokenType JsonStreamParser::GetNextTokenType() {
+ SkipWhitespace();
+
+ int size = p_.size();
+ if (size == 0) {
+ // If we ran out of data, report unknown and we'll place the previous parse
+ // type onto the stack and try again when we have more data.
+ return UNKNOWN;
+ }
+ // TODO(sven): Split this method based on context since different contexts
+ // support different tokens. Would slightly speed up processing?
+ const char* data = p_.data();
+ if (*data == '\"' || *data == '\'') return BEGIN_STRING;
+ if (*data == '-' || ('0' <= *data && *data <= '9')) {
+ return BEGIN_NUMBER;
+ }
+ if (size >= true_len && !strncmp(data, "true", true_len)) {
+ return BEGIN_TRUE;
+ }
+ if (size >= false_len && !strncmp(data, "false", false_len)) {
+ return BEGIN_FALSE;
+ }
+ if (size >= null_len && !strncmp(data, "null", null_len)) {
+ return BEGIN_NULL;
+ }
+ if (*data == '{') return BEGIN_OBJECT;
+ if (*data == '}') return END_OBJECT;
+ if (*data == '[') return BEGIN_ARRAY;
+ if (*data == ']') return END_ARRAY;
+ if (*data == ':') return ENTRY_SEPARATOR;
+ if (*data == ',') return VALUE_SEPARATOR;
+ if (MatchKey(p_)) {
+ return BEGIN_KEY;
+ }
+
+ // We don't know that we necessarily have an invalid token here, just that we
+ // can't parse what we have so far. So we don't report an error and just
+ // return UNKNOWN so we can try again later when we have more data, or if we
+ // finish and we have leftovers.
+ return UNKNOWN;
+}
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/json_stream_parser.h b/src/google/protobuf/util/internal/json_stream_parser.h
new file mode 100644
index 00000000..17b094ae
--- /dev/null
+++ b/src/google/protobuf/util/internal/json_stream_parser.h
@@ -0,0 +1,256 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__
+
+#include <stack>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/status.h>
+
+namespace google {
+namespace util {
+class Status;
+} // namespace util
+
+namespace protobuf {
+namespace util {
+namespace converter {
+
+class ObjectWriter;
+
+// A JSON parser that can parse a stream of JSON chunks rather than needing the
+// entire JSON string up front. It is a modified version of the parser in
+// //net/proto/json/json-parser.h that has been changed in the following ways:
+// - Changed from recursion to an explicit stack to allow resumption
+// - Added support for int64 and uint64 numbers
+// - Removed support for octal and decimal escapes
+// - Removed support for numeric keys
+// - Removed support for functions (javascript)
+// - Removed some lax-comma support (but kept trailing comma support)
+// - Writes directly to an ObjectWriter rather than using subclassing
+//
+// Here is an example usage:
+// JsonStreamParser parser(ow_.get());
+// util::Status result = parser.Parse(chunk1);
+// result.Update(parser.Parse(chunk2));
+// result.Update(parser.FinishParse());
+// GOOGLE_DCHECK(result.ok()) << "Failed to parse JSON";
+//
+// This parser is thread-compatible as long as only one thread is calling a
+// Parse() method at a time.
+class LIBPROTOBUF_EXPORT JsonStreamParser {
+ public:
+ // Creates a JsonStreamParser that will write to the given ObjectWriter.
+ explicit JsonStreamParser(ObjectWriter* ow);
+ virtual ~JsonStreamParser();
+
+ // Parse a JSON string (UTF-8 encoded).
+ util::Status Parse(StringPiece json);
+
+ // Finish parsing the JSON string.
+ util::Status FinishParse();
+
+ private:
+ enum TokenType {
+ BEGIN_STRING, // " or '
+ BEGIN_NUMBER, // - or digit
+ BEGIN_TRUE, // true
+ BEGIN_FALSE, // false
+ BEGIN_NULL, // null
+ BEGIN_OBJECT, // {
+ END_OBJECT, // }
+ BEGIN_ARRAY, // [
+ END_ARRAY, // ]
+ ENTRY_SEPARATOR, // :
+ VALUE_SEPARATOR, // ,
+ BEGIN_KEY, // letter, _, $ or digit. Must begin with non-digit
+ UNKNOWN // Unknown token or we ran out of the stream.
+ };
+
+ enum ParseType {
+ VALUE, // Expects a {, [, true, false, null, string or number
+ OBJ_MID, // Expects a ',' or }
+ ENTRY, // Expects a key or }
+ ENTRY_MID, // Expects a :
+ ARRAY_VALUE, // Expects a value or ]
+ ARRAY_MID // Expects a ',' or ]
+ };
+
+ // Holds the result of parsing a number
+ struct NumberResult {
+ enum Type { DOUBLE, INT, UINT };
+ Type type;
+ union {
+ double double_val;
+ int64 int_val;
+ uint64 uint_val;
+ };
+ };
+
+ // Parses a single chunk of JSON, returning an error if the JSON was invalid.
+ util::Status ParseChunk(StringPiece json);
+
+ // Runs the parser based on stack_ and p_, until the stack is empty or p_ runs
+ // out of data. If we unexpectedly run out of p_ we push the latest back onto
+ // the stack and return.
+ util::Status RunParser();
+
+ // Parses a value from p_ and writes it to ow_.
+ // A value may be an object, array, true, false, null, string or number.
+ util::Status ParseValue(TokenType type);
+
+ // Parses a string and writes it out to the ow_.
+ util::Status ParseString();
+
+ // Parses a string, storing the result in parsed_.
+ util::Status ParseStringHelper();
+
+ // This function parses unicode escape sequences in strings. It returns an
+ // error when there's a parsing error, either the size is not the expected
+ // size or a character is not a hex digit. When it returns str will contain
+ // what has been successfully parsed so far.
+ util::Status ParseUnicodeEscape();
+
+ // Expects p_ to point to a JSON number, writes the number to the writer using
+ // the appropriate Render method based on the type of number.
+ util::Status ParseNumber();
+
+ // Parse a number into a NumberResult, reporting an error if no number could
+ // be parsed. This method will try to parse into a uint64, int64, or double
+ // based on whether the number was positive or negative or had a decimal
+ // component.
+ util::Status ParseNumberHelper(NumberResult* result);
+
+ // Handles a { during parsing of a value.
+ util::Status HandleBeginObject();
+
+ // Parses from the ENTRY state.
+ util::Status ParseEntry(TokenType type);
+
+ // Parses from the ENTRY_MID state.
+ util::Status ParseEntryMid(TokenType type);
+
+ // Parses from the OBJ_MID state.
+ util::Status ParseObjectMid(TokenType type);
+
+ // Handles a [ during parsing of a value.
+ util::Status HandleBeginArray();
+
+ // Parses from the ARRAY_VALUE state.
+ util::Status ParseArrayValue(TokenType type);
+
+ // Parses from the ARRAY_MID state.
+ util::Status ParseArrayMid(TokenType type);
+
+ // Expects p_ to point to an unquoted literal
+ util::Status ParseTrue();
+ util::Status ParseFalse();
+ util::Status ParseNull();
+
+ // Report a failure as a util::Status.
+ util::Status ReportFailure(StringPiece message);
+
+ // Report a failure due to an UNKNOWN token type. We check if we hit the
+ // end of the stream and if we're finishing or not to detect what type of
+ // status to return in this case.
+ util::Status ReportUnknown(StringPiece message);
+
+ // Advance p_ past all whitespace or until the end of the string.
+ void SkipWhitespace();
+
+ // Advance p_ one UTF-8 character
+ void Advance();
+
+ // Expects p_ to point to the beginning of a key.
+ util::Status ParseKey();
+
+ // Return the type of the next token at p_.
+ TokenType GetNextTokenType();
+
+ // The object writer to write parse events to.
+ ObjectWriter* ow_;
+
+ // The stack of parsing we still need to do. When the stack runs empty we will
+ // have parsed a single value from the root (e.g. an object or list).
+ std::stack<ParseType> stack_;
+
+ // Contains any leftover text from a previous chunk that we weren't able to
+ // fully parse, for example the start of a key or number.
+ string leftover_;
+
+ // The current chunk of JSON being parsed. Primarily used for providing
+ // context during error reporting.
+ StringPiece json_;
+
+ // A pointer within the current JSON being parsed, used to track location.
+ StringPiece p_;
+
+ // Stores the last key read, as we separate parsing of keys and values.
+ StringPiece key_;
+
+ // Storage for key_ if we need to keep ownership, for example between chunks
+ // or if the key was unescaped from a JSON string.
+ string key_storage_;
+
+ // True during the FinishParse() call, so we know that any errors are fatal.
+ // For example an unterminated string will normally result in cancelling and
+ // trying during the next chunk, but during FinishParse() it is an error.
+ bool finishing_;
+
+ // String we parsed during a call to ParseStringHelper().
+ StringPiece parsed_;
+
+ // Storage for the string we parsed. This may be empty if the string was able
+ // to be parsed directly from the input.
+ string parsed_storage_;
+
+ // The character that opened the string, either ' or ".
+ // A value of 0 indicates that string parsing is not in process.
+ char string_open_;
+
+ // Storage for utf8-coerced bytes.
+ google::protobuf::scoped_array<char> utf8_storage_;
+
+ // Length of the storage for utf8-coerced bytes.
+ int utf8_length_;
+
+ GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonStreamParser);
+};
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__
diff --git a/src/google/protobuf/util/internal/json_stream_parser_test.cc b/src/google/protobuf/util/internal/json_stream_parser_test.cc
new file mode 100644
index 00000000..b0775a2f
--- /dev/null
+++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc
@@ -0,0 +1,702 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/json_stream_parser.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/time.h>
+#include <google/protobuf/util/internal/expecting_objectwriter.h>
+#include <google/protobuf/util/internal/object_writer.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/status.h>
+
+
+namespace google {
+namespace protobuf {
+namespace util {
+using util::Status;
+namespace error {
+using util::error::INVALID_ARGUMENT;
+} // namespace error
+namespace converter {
+
+using util::Status;
+
+// Tests for the JSON Stream Parser. These tests are intended to be
+// comprehensive and cover the following:
+//
+// Positive tests:
+// - true, false, null
+// - empty object or array.
+// - negative and positive double and int, unsigned int
+// - single and double quoted strings
+// - string key, unquoted key, numeric key
+// - array containing array, object, value
+// - object containing array, object, value
+// - unicode handling in strings
+// - ascii escaping (\b, \f, \n, \r, \t, \v)
+// - trailing commas
+//
+// Negative tests:
+// - illegal literals
+// - mismatched quotes failure on strings
+// - unterminated string failure
+// - unexpected end of string failure
+// - mismatched object and array closing
+// - Failure to close array or object
+// - numbers too large
+// - invalid unicode escapes.
+// - invalid unicode sequences.
+// - numbers as keys
+//
+// For each test we split the input string on every possible character to ensure
+// the parser is able to handle arbitrarily split input for all cases. We also
+// do a final test of the entire test case one character at a time.
+class JsonStreamParserTest : public ::testing::Test {
+ protected:
+ JsonStreamParserTest() : mock_(), ow_(&mock_) {}
+ virtual ~JsonStreamParserTest() {}
+
+ util::Status RunTest(StringPiece json, int split) {
+ JsonStreamParser parser(&mock_);
+
+ // Special case for split == length, test parsing one character at a time.
+ if (split == json.length()) {
+ GOOGLE_LOG(INFO) << "Testing split every char: " << json;
+ for (int i = 0; i < json.length(); ++i) {
+ StringPiece single = json.substr(i, 1);
+ util::Status result = parser.Parse(single);
+ if (!result.ok()) {
+ return result;
+ }
+ }
+ return parser.FinishParse();
+ }
+
+ // Normal case, split at the split point and parse two substrings.
+ StringPiece first = json.substr(0, split);
+ StringPiece rest = json.substr(split);
+ GOOGLE_LOG(INFO) << "Testing split: " << first << "><" << rest;
+ util::Status result = parser.Parse(first);
+ if (result.ok()) {
+ result = parser.Parse(rest);
+ if (result.ok()) {
+ result = parser.FinishParse();
+ }
+ }
+ return result;
+ }
+
+ void DoTest(StringPiece json, int split) {
+ util::Status result = RunTest(json, split);
+ if (!result.ok()) {
+ GOOGLE_LOG(WARNING) << result;
+ }
+ EXPECT_OK(result);
+ }
+
+ void DoErrorTest(StringPiece json, int split, StringPiece error_prefix) {
+ util::Status result = RunTest(json, split);
+ EXPECT_EQ(util::error::INVALID_ARGUMENT, result.error_code());
+ StringPiece error_message(result.error_message());
+ EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size()));
+ }
+
+
+ MockObjectWriter mock_;
+ ExpectingObjectWriter ow_;
+};
+
+
+// Positive tests
+
+// - true, false, null
+TEST_F(JsonStreamParserTest, SimpleTrue) {
+ StringPiece str = "true";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.RenderBool("", true);
+ DoTest(str, i);
+ }
+}
+
+TEST_F(JsonStreamParserTest, SimpleFalse) {
+ StringPiece str = "false";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.RenderBool("", false);
+ DoTest(str, i);
+ }
+}
+
+TEST_F(JsonStreamParserTest, SimpleNull) {
+ StringPiece str = "null";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.RenderNull("");
+ DoTest(str, i);
+ }
+}
+
+// - empty object and array.
+TEST_F(JsonStreamParserTest, EmptyObject) {
+ StringPiece str = "{}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("")->EndObject();
+ DoTest(str, i);
+ }
+}
+
+TEST_F(JsonStreamParserTest, EmptyList) {
+ StringPiece str = "[]";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartList("")->EndList();
+ DoTest(str, i);
+ }
+}
+
+// - negative and positive double and int, unsigned int
+TEST_F(JsonStreamParserTest, SimpleDouble) {
+ StringPiece str = "42.5";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.RenderDouble("", 42.5);
+ DoTest(str, i);
+ }
+}
+
+TEST_F(JsonStreamParserTest, ScientificDouble) {
+ StringPiece str = "1.2345e-10";
+ for (int i = 0; i < str.length(); ++i) {
+ ow_.RenderDouble("", 1.2345e-10);
+ DoTest(str, i);
+ }
+}
+
+TEST_F(JsonStreamParserTest, SimpleNegativeDouble) {
+ StringPiece str = "-1045.235";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.RenderDouble("", -1045.235);
+ DoTest(str, i);
+ }
+}
+
+TEST_F(JsonStreamParserTest, SimpleInt) {
+ StringPiece str = "123456";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.RenderUint64("", 123456);
+ DoTest(str, i);
+ }
+}
+
+TEST_F(JsonStreamParserTest, SimpleNegativeInt) {
+ StringPiece str = "-79497823553162765";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.RenderInt64("", -79497823553162765LL);
+ DoTest(str, i);
+ }
+}
+
+TEST_F(JsonStreamParserTest, SimpleUnsignedInt) {
+ StringPiece str = "11779497823553162765";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.RenderUint64("", 11779497823553162765ULL);
+ DoTest(str, i);
+ }
+}
+
+// - single and double quoted strings
+TEST_F(JsonStreamParserTest, EmptyDoubleQuotedString) {
+ StringPiece str = "\"\"";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.RenderString("", "");
+ DoTest(str, i);
+ }
+}
+
+TEST_F(JsonStreamParserTest, EmptySingleQuotedString) {
+ StringPiece str = "''";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.RenderString("", "");
+ DoTest(str, i);
+ }
+}
+
+TEST_F(JsonStreamParserTest, SimpleDoubleQuotedString) {
+ StringPiece str = "\"Some String\"";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.RenderString("", "Some String");
+ DoTest(str, i);
+ }
+}
+
+TEST_F(JsonStreamParserTest, SimpleSingleQuotedString) {
+ StringPiece str = "'Another String'";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.RenderString("", "Another String");
+ DoTest(str, i);
+ }
+}
+
+// - string key, unquoted key, numeric key
+TEST_F(JsonStreamParserTest, ObjectKeyTypes) {
+ StringPiece str =
+ "{'s': true, \"d\": false, key: null, snake_key: [], camelKey: {}}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("")
+ ->RenderBool("s", true)
+ ->RenderBool("d", false)
+ ->RenderNull("key")
+ ->StartList("snake_key")
+ ->EndList()
+ ->StartObject("camelKey")
+ ->EndObject()
+ ->EndObject();
+ DoTest(str, i);
+ }
+}
+
+// - array containing array, object, values (true, false, null, num, string)
+TEST_F(JsonStreamParserTest, ArrayValues) {
+ StringPiece str =
+ "[true, false, null, 'a string', \"another string\", [22, -127, 45.3, "
+ "-1056.4, 11779497823553162765], {'key': true}]";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartList("")
+ ->RenderBool("", true)
+ ->RenderBool("", false)
+ ->RenderNull("")
+ ->RenderString("", "a string")
+ ->RenderString("", "another string")
+ ->StartList("")
+ ->RenderUint64("", 22)
+ ->RenderInt64("", -127)
+ ->RenderDouble("", 45.3)
+ ->RenderDouble("", -1056.4)
+ ->RenderUint64("", 11779497823553162765ULL)
+ ->EndList()
+ ->StartObject("")
+ ->RenderBool("key", true)
+ ->EndObject()
+ ->EndList();
+ DoTest(str, i);
+ }
+}
+
+// - object containing array, object, value (true, false, null, num, string)
+TEST_F(JsonStreamParserTest, ObjectValues) {
+ StringPiece str =
+ "{t: true, f: false, n: null, s: 'a string', d: \"another string\", pi: "
+ "22, ni: -127, pd: 45.3, nd: -1056.4, pl: 11779497823553162765, l: [[]], "
+ "o: {'key': true}}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("")
+ ->RenderBool("t", true)
+ ->RenderBool("f", false)
+ ->RenderNull("n")
+ ->RenderString("s", "a string")
+ ->RenderString("d", "another string")
+ ->RenderUint64("pi", 22)
+ ->RenderInt64("ni", -127)
+ ->RenderDouble("pd", 45.3)
+ ->RenderDouble("nd", -1056.4)
+ ->RenderUint64("pl", 11779497823553162765ULL)
+ ->StartList("l")
+ ->StartList("")
+ ->EndList()
+ ->EndList()
+ ->StartObject("o")
+ ->RenderBool("key", true)
+ ->EndObject()
+ ->EndObject();
+ DoTest(str, i);
+ }
+}
+
+#ifndef _MSC_VER
+// - unicode handling in strings
+TEST_F(JsonStreamParserTest, UnicodeEscaping) {
+ StringPiece str = "[\"\\u0639\\u0631\\u0628\\u0649\"]";
+ for (int i = 0; i <= str.length(); ++i) {
+ // TODO(xiaofeng): Figure out what default encoding to use for JSON strings.
+ // In protobuf we use UTF-8 for strings, but for JSON we probably should allow
+ // different encodings?
+ ow_.StartList("")->RenderString("", "\u0639\u0631\u0628\u0649")->EndList();
+ DoTest(str, i);
+ }
+}
+#endif
+
+// - ascii escaping (\b, \f, \n, \r, \t, \v)
+TEST_F(JsonStreamParserTest, AsciiEscaping) {
+ StringPiece str =
+ "[\"\\b\", \"\\ning\", \"test\\f\", \"\\r\\t\", \"test\\\\\\ving\"]";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartList("")
+ ->RenderString("", "\b")
+ ->RenderString("", "\ning")
+ ->RenderString("", "test\f")
+ ->RenderString("", "\r\t")
+ ->RenderString("", "test\\\ving")
+ ->EndList();
+ DoTest(str, i);
+ }
+}
+
+// - trailing commas, we support a single trailing comma but no internal commas.
+TEST_F(JsonStreamParserTest, TrailingCommas) {
+ StringPiece str = "[['a',true,], {b: null,},]";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartList("")
+ ->StartList("")
+ ->RenderString("", "a")
+ ->RenderBool("", true)
+ ->EndList()
+ ->StartObject("")
+ ->RenderNull("b")
+ ->EndObject()
+ ->EndList();
+ DoTest(str, i);
+ }
+}
+
+// Negative tests
+
+// illegal literals
+TEST_F(JsonStreamParserTest, ExtraTextAfterTrue) {
+ StringPiece str = "truee";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.RenderBool("", true);
+ DoErrorTest(str, i, "Parsing terminated before end of input.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, InvalidNumberDashOnly) {
+ StringPiece str = "-";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Unable to parse number.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, InvalidNumberDashName) {
+ StringPiece str = "-foo";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Unable to parse number.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, InvalidLiteralInArray) {
+ StringPiece str = "[nule]";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartList("");
+ DoErrorTest(str, i, "Unexpected token.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, InvalidLiteralInObject) {
+ StringPiece str = "{123false}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("");
+ DoErrorTest(str, i, "Expected an object key or }.");
+ }
+}
+
+// mismatched quotes failure on strings
+TEST_F(JsonStreamParserTest, MismatchedSingleQuotedLiteral) {
+ StringPiece str = "'Some str\"";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Closing quote expected in string.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, MismatchedDoubleQuotedLiteral) {
+ StringPiece str = "\"Another string that ends poorly!'";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Closing quote expected in string.");
+ }
+}
+
+// unterminated strings
+TEST_F(JsonStreamParserTest, UnterminatedLiteralString) {
+ StringPiece str = "\"Forgot the rest of i";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Closing quote expected in string.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, UnterminatedStringEscape) {
+ StringPiece str = "\"Forgot the rest of \\";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Closing quote expected in string.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, UnterminatedStringInArray) {
+ StringPiece str = "[\"Forgot to close the string]";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartList("");
+ DoErrorTest(str, i, "Closing quote expected in string.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, UnterminatedStringInObject) {
+ StringPiece str = "{f: \"Forgot to close the string}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("");
+ DoErrorTest(str, i, "Closing quote expected in string.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, UnterminatedObject) {
+ StringPiece str = "{";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("");
+ DoErrorTest(str, i, "Unexpected end of string.");
+ }
+}
+
+
+// mismatched object and array closing
+TEST_F(JsonStreamParserTest, MismatchedCloseObject) {
+ StringPiece str = "{'key': true]";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("")->RenderBool("key", true);
+ DoErrorTest(str, i, "Expected , or } after key:value pair.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, MismatchedCloseArray) {
+ StringPiece str = "[true, null}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartList("")->RenderBool("", true)->RenderNull("");
+ DoErrorTest(str, i, "Expected , or ] after array value.");
+ }
+}
+
+// Invalid object keys.
+TEST_F(JsonStreamParserTest, InvalidNumericObjectKey) {
+ StringPiece str = "{42: true}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("");
+ DoErrorTest(str, i, "Expected an object key or }.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, InvalidLiteralObjectInObject) {
+ StringPiece str = "{{bob: true}}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("");
+ DoErrorTest(str, i, "Expected an object key or }.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, InvalidLiteralArrayInObject) {
+ StringPiece str = "{[null]}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("");
+ DoErrorTest(str, i, "Expected an object key or }.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, InvalidLiteralValueInObject) {
+ StringPiece str = "{false}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("");
+ DoErrorTest(str, i, "Expected an object key or }.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, MissingColonAfterStringInObject) {
+ StringPiece str = "{\"key\"}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("");
+ DoErrorTest(str, i, "Expected : between key:value pair.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, MissingColonAfterKeyInObject) {
+ StringPiece str = "{key}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("");
+ DoErrorTest(str, i, "Expected : between key:value pair.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, EndOfTextAfterKeyInObject) {
+ StringPiece str = "{key";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("");
+ DoErrorTest(str, i, "Unexpected end of string.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, MissingValueAfterColonInObject) {
+ StringPiece str = "{key:}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("");
+ DoErrorTest(str, i, "Unexpected token.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, MissingCommaBetweenObjectEntries) {
+ StringPiece str = "{key:20 'hello': true}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("")->RenderUint64("key", 20);
+ DoErrorTest(str, i, "Expected , or } after key:value pair.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, InvalidLiteralAsObjectKey) {
+ StringPiece str = "{false: 20}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("");
+ DoErrorTest(str, i, "Expected an object key or }.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, ExtraCharactersAfterObject) {
+ StringPiece str = "{}}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("")->EndObject();
+ DoErrorTest(str, i, "Parsing terminated before end of input.");
+ }
+}
+
+// numbers too large
+TEST_F(JsonStreamParserTest, PositiveNumberTooBig) {
+ StringPiece str = "[18446744073709551616]"; // 2^64
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartList("");
+ DoErrorTest(str, i, "Unable to parse number.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, NegativeNumberTooBig) {
+ StringPiece str = "[-18446744073709551616]";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartList("");
+ DoErrorTest(str, i, "Unable to parse number.");
+ }
+}
+
+/*
+TODO(sven): Fail parsing when parsing a double that is too large.
+
+TEST_F(JsonStreamParserTest, DoubleTooBig) {
+ StringPiece str = "[184464073709551232321616.45]";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartList("");
+ DoErrorTest(str, i, "Unable to parse number");
+ }
+}
+*/
+
+// invalid unicode sequence.
+TEST_F(JsonStreamParserTest, UnicodeEscapeCutOff) {
+ StringPiece str = "\"\\u12";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Illegal hex string.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, UnicodeEscapeInvalidCharacters) {
+ StringPiece str = "\"\\u12$4hello";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Invalid escape sequence.");
+ }
+}
+
+// Extra commas with an object or array.
+TEST_F(JsonStreamParserTest, ExtraCommaInObject) {
+ StringPiece str = "{'k1': true,,'k2': false}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("")->RenderBool("k1", true);
+ DoErrorTest(str, i, "Expected an object key or }.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, ExtraCommaInArray) {
+ StringPiece str = "[true,,false}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartList("")->RenderBool("", true);
+ DoErrorTest(str, i, "Unexpected token.");
+ }
+}
+
+// Extra text beyond end of value.
+TEST_F(JsonStreamParserTest, ExtraTextAfterLiteral) {
+ StringPiece str = "'hello', 'world'";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.RenderString("", "hello");
+ DoErrorTest(str, i, "Parsing terminated before end of input.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, ExtraTextAfterObject) {
+ StringPiece str = "{'key': true} 'oops'";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("")->RenderBool("key", true)->EndObject();
+ DoErrorTest(str, i, "Parsing terminated before end of input.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, ExtraTextAfterArray) {
+ StringPiece str = "[null] 'oops'";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartList("")->RenderNull("")->EndList();
+ DoErrorTest(str, i, "Parsing terminated before end of input.");
+ }
+}
+
+// Random unknown text in the value.
+TEST_F(JsonStreamParserTest, UnknownCharactersAsValue) {
+ StringPiece str = "*&#25";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Expected a value.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, UnknownCharactersInArray) {
+ StringPiece str = "[*&#25]";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartList("");
+ DoErrorTest(str, i, "Expected a value or ] within an array.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, UnknownCharactersInObject) {
+ StringPiece str = "{'key': *&#25}";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartObject("");
+ DoErrorTest(str, i, "Expected a value.");
+ }
+}
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/location_tracker.h b/src/google/protobuf/util/internal/location_tracker.h
new file mode 100644
index 00000000..0864b057
--- /dev/null
+++ b/src/google/protobuf/util/internal/location_tracker.h
@@ -0,0 +1,65 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_LOCATION_TRACKER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_LOCATION_TRACKER_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// LocationTrackerInterface is an interface for classes that track
+// the location information for the purpose of error reporting.
+class LIBPROTOBUF_EXPORT LocationTrackerInterface {
+ public:
+ virtual ~LocationTrackerInterface() {}
+
+ // Returns the object location as human readable string.
+ virtual string ToString() const = 0;
+
+ protected:
+ LocationTrackerInterface() {}
+
+ private:
+ // Please do not add any data members to this class.
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LocationTrackerInterface);
+};
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_LOCATION_TRACKER_H__
diff --git a/src/google/protobuf/util/internal/mock_error_listener.h b/src/google/protobuf/util/internal/mock_error_listener.h
new file mode 100644
index 00000000..591c35db
--- /dev/null
+++ b/src/google/protobuf/util/internal/mock_error_listener.h
@@ -0,0 +1,63 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_MOCK_ERROR_LISTENER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_MOCK_ERROR_LISTENER_H__
+
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/util/internal/error_listener.h>
+#include <google/protobuf/util/internal/location_tracker.h>
+#include <gmock/gmock.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+class MockErrorListener : public ErrorListener {
+ public:
+ MockErrorListener() {}
+ virtual ~MockErrorListener() {}
+
+ MOCK_METHOD3(InvalidName, void(const LocationTrackerInterface& loc,
+ StringPiece unknown_name,
+ StringPiece message));
+ MOCK_METHOD3(InvalidValue, void(const LocationTrackerInterface& loc,
+ StringPiece type_name, StringPiece value));
+ MOCK_METHOD2(MissingField, void(const LocationTrackerInterface& loc,
+ StringPiece missing_name));
+};
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_MOCK_ERROR_LISTENER_H__
diff --git a/src/google/protobuf/util/internal/object_location_tracker.h b/src/google/protobuf/util/internal/object_location_tracker.h
new file mode 100644
index 00000000..8586cecc
--- /dev/null
+++ b/src/google/protobuf/util/internal/object_location_tracker.h
@@ -0,0 +1,64 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_LOCATION_TRACKER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_LOCATION_TRACKER_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/util/internal/location_tracker.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// An empty concrete implementation of LocationTrackerInterface.
+class ObjectLocationTracker : public LocationTrackerInterface {
+ public:
+ // Creates an empty location tracker.
+ ObjectLocationTracker() {}
+
+ virtual ~ObjectLocationTracker() {}
+
+ // Returns empty because nothing is tracked.
+ virtual string ToString() const { return ""; }
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectLocationTracker);
+};
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_LOCATION_TRACKER_H__
diff --git a/src/google/protobuf/util/internal/object_source.h b/src/google/protobuf/util/internal/object_source.h
new file mode 100644
index 00000000..2c31cfb0
--- /dev/null
+++ b/src/google/protobuf/util/internal/object_source.h
@@ -0,0 +1,79 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/status.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+class ObjectWriter;
+
+// An ObjectSource is anything that can write to an ObjectWriter.
+// Implementation of this interface typically provide constructors or
+// factory methods to create an instance based on some source data, for
+// example, a character stream, or protobuf.
+//
+// Derived classes could be thread-unsafe.
+class LIBPROTOBUF_EXPORT ObjectSource {
+ public:
+ virtual ~ObjectSource() {}
+
+ // Writes to the ObjectWriter
+ virtual util::Status WriteTo(ObjectWriter* ow) const {
+ return NamedWriteTo("", ow);
+ }
+
+ // Writes to the ObjectWriter with a custom name for the message.
+ // This is useful when you chain ObjectSource together by embedding one
+ // within another.
+ virtual util::Status NamedWriteTo(StringPiece name,
+ ObjectWriter* ow) const = 0;
+
+ protected:
+ ObjectSource() {}
+
+ private:
+ // Do not add any data members to this class.
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectSource);
+};
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__
diff --git a/src/google/protobuf/util/internal/object_writer.cc b/src/google/protobuf/util/internal/object_writer.cc
new file mode 100644
index 00000000..57cc08a1
--- /dev/null
+++ b/src/google/protobuf/util/internal/object_writer.cc
@@ -0,0 +1,92 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/object_writer.h>
+
+#include <google/protobuf/util/internal/datapiece.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// static
+void ObjectWriter::RenderDataPieceTo(const DataPiece& data, StringPiece name,
+ ObjectWriter* ow) {
+ switch (data.type()) {
+ case DataPiece::TYPE_INT32: {
+ ow->RenderInt32(name, data.ToInt32().ValueOrDie());
+ break;
+ }
+ case DataPiece::TYPE_INT64: {
+ ow->RenderInt64(name, data.ToInt64().ValueOrDie());
+ break;
+ }
+ case DataPiece::TYPE_UINT32: {
+ ow->RenderUint32(name, data.ToUint32().ValueOrDie());
+ break;
+ }
+ case DataPiece::TYPE_UINT64: {
+ ow->RenderUint64(name, data.ToUint64().ValueOrDie());
+ break;
+ }
+ case DataPiece::TYPE_DOUBLE: {
+ ow->RenderDouble(name, data.ToDouble().ValueOrDie());
+ break;
+ }
+ case DataPiece::TYPE_FLOAT: {
+ ow->RenderFloat(name, data.ToFloat().ValueOrDie());
+ break;
+ }
+ case DataPiece::TYPE_BOOL: {
+ ow->RenderBool(name, data.ToBool().ValueOrDie());
+ break;
+ }
+ case DataPiece::TYPE_STRING: {
+ ow->RenderString(name, data.ToString().ValueOrDie());
+ break;
+ }
+ case DataPiece::TYPE_BYTES: {
+ ow->RenderBytes(name, data.ToBytes().ValueOrDie());
+ break;
+ }
+ case DataPiece::TYPE_NULL: {
+ ow->RenderNull(name);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/object_writer.h b/src/google/protobuf/util/internal/object_writer.h
new file mode 100644
index 00000000..20bd3627
--- /dev/null
+++ b/src/google/protobuf/util/internal/object_writer.h
@@ -0,0 +1,126 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringpiece.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+class DataPiece;
+
+// An ObjectWriter is an interface for writing a stream of events
+// representing objects and collections. Implementation of this
+// interface can be used to write an object stream to an in-memory
+// structure, protobufs, JSON, XML, or any other output format
+// desired. The ObjectSource interface is typically used as the
+// source of an object stream.
+//
+// See JsonObjectWriter for a sample implementation of ObjectWriter
+// and its use.
+//
+// Derived classes could be thread-unsafe.
+//
+// TODO(xinb): seems like a prime candidate to apply the RAII paradigm
+// and get rid the need to call EndXXX().
+class LIBPROTOBUF_EXPORT ObjectWriter {
+ public:
+ virtual ~ObjectWriter() {}
+
+ // Starts an object. If the name is empty, the object will not be named.
+ virtual ObjectWriter* StartObject(StringPiece name) = 0;
+
+ // Ends an object.
+ virtual ObjectWriter* EndObject() = 0;
+
+ // Starts a list. If the name is empty, the list will not be named.
+ virtual ObjectWriter* StartList(StringPiece name) = 0;
+
+ // Ends a list.
+ virtual ObjectWriter* EndList() = 0;
+
+ // Renders a boolean value.
+ virtual ObjectWriter* RenderBool(StringPiece name, bool value) = 0;
+
+ // Renders an 32-bit integer value.
+ virtual ObjectWriter* RenderInt32(StringPiece name, int32 value) = 0;
+
+ // Renders an 32-bit unsigned integer value.
+ virtual ObjectWriter* RenderUint32(StringPiece name, uint32 value) = 0;
+
+ // Renders a 64-bit integer value.
+ virtual ObjectWriter* RenderInt64(StringPiece name, int64 value) = 0;
+
+ // Renders an 64-bit unsigned integer value.
+ virtual ObjectWriter* RenderUint64(StringPiece name, uint64 value) = 0;
+
+ // Renders a double value.
+ virtual ObjectWriter* RenderDouble(StringPiece name, double value) = 0;
+
+ // Renders a float value.
+ virtual ObjectWriter* RenderFloat(StringPiece name, float value) = 0;
+
+ // Renders a StringPiece value. This is for rendering strings.
+ virtual ObjectWriter* RenderString(StringPiece name, StringPiece value) = 0;
+
+ // Renders a bytes value.
+ virtual ObjectWriter* RenderBytes(StringPiece name, StringPiece value) = 0;
+
+ // Renders a Null value.
+ virtual ObjectWriter* RenderNull(StringPiece name) = 0;
+
+ // Disables case normalization. Any RenderTYPE call after calling this
+ // function will output the name field as-is. No normalization is attempted on
+ // it. This setting is reset immediately after the next RenderTYPE is called.
+ virtual ObjectWriter* DisableCaseNormalizationForNextKey() { return this; }
+
+ // Renders a DataPiece object to a ObjectWriter.
+ static void RenderDataPieceTo(const DataPiece& data, StringPiece name,
+ ObjectWriter* ow);
+
+ protected:
+ ObjectWriter() {}
+
+ private:
+ // Do not add any data members to this class.
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectWriter);
+};
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc
new file mode 100644
index 00000000..53a0e47a
--- /dev/null
+++ b/src/google/protobuf/util/internal/protostream_objectsource.cc
@@ -0,0 +1,1051 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/protostream_objectsource.h>
+
+#include <utility>
+
+#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/stubs/time.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/util/internal/field_mask_utility.h>
+#include <google/protobuf/util/internal/constants.h>
+#include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/status_macros.h>
+
+
+namespace google {
+namespace protobuf {
+namespace util {
+using util::Status;
+using util::StatusOr;
+namespace error {
+using util::error::Code;
+using util::error::INTERNAL;
+}
+namespace converter {
+
+using google::protobuf::Descriptor;
+using google::protobuf::EnumValueDescriptor;
+using google::protobuf::FieldDescriptor;
+using google::protobuf::internal::WireFormat;
+using google::protobuf::internal::WireFormatLite;
+using util::Status;
+using util::StatusOr;
+
+namespace {
+// Finds a field with the given number. NULL if none found.
+const google::protobuf::Field* FindFieldByNumber(
+ const google::protobuf::Type& type, int number);
+
+// Returns true if the field is packable.
+bool IsPackable(const google::protobuf::Field& field);
+
+// Finds an enum value with the given number. NULL if none found.
+const google::protobuf::EnumValue* FindEnumValueByNumber(
+ const google::protobuf::Enum& tech_enum, int number);
+
+// Utility function to format nanos.
+const string FormatNanos(uint32 nanos);
+} // namespace
+
+
+ProtoStreamObjectSource::ProtoStreamObjectSource(
+ google::protobuf::io::CodedInputStream* stream, TypeResolver* type_resolver,
+ const google::protobuf::Type& type)
+ : stream_(stream),
+ typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
+ own_typeinfo_(true),
+ type_(type) {
+ GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL.";
+}
+
+ProtoStreamObjectSource::ProtoStreamObjectSource(
+ google::protobuf::io::CodedInputStream* stream, TypeInfo* typeinfo,
+ const google::protobuf::Type& type)
+ : stream_(stream), typeinfo_(typeinfo), own_typeinfo_(false), type_(type) {
+ GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL.";
+}
+
+ProtoStreamObjectSource::~ProtoStreamObjectSource() {
+ if (own_typeinfo_) {
+ delete typeinfo_;
+ }
+}
+
+Status ProtoStreamObjectSource::NamedWriteTo(StringPiece name,
+ ObjectWriter* ow) const {
+ return WriteMessage(type_, name, 0, true, ow);
+}
+
+const google::protobuf::Field* ProtoStreamObjectSource::FindAndVerifyField(
+ const google::protobuf::Type& type, uint32 tag) const {
+ // Lookup the new field in the type by tag number.
+ const google::protobuf::Field* field = FindFieldByNumber(type, tag >> 3);
+ // Verify if the field corresponds to the wire type in tag.
+ // If there is any discrepancy, mark the field as not found.
+ if (field != NULL) {
+ WireFormatLite::WireType expected_type =
+ WireFormatLite::WireTypeForFieldType(
+ static_cast<WireFormatLite::FieldType>(field->kind()));
+ WireFormatLite::WireType actual_type = WireFormatLite::GetTagWireType(tag);
+ if (actual_type != expected_type &&
+ (!IsPackable(*field) ||
+ actual_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) {
+ field = NULL;
+ }
+ }
+ return field;
+}
+
+Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type,
+ StringPiece name,
+ const uint32 end_tag,
+ bool include_start_and_end,
+ ObjectWriter* ow) const {
+ const TypeRenderer* type_renderer = FindTypeRenderer(type.name());
+ if (type_renderer != NULL) {
+ return (*type_renderer)(this, type, name, ow);
+ }
+
+ const google::protobuf::Field* field = NULL;
+ string field_name;
+ // last_tag set to dummy value that is different from tag.
+ uint32 tag = stream_->ReadTag(), last_tag = tag + 1;
+
+ if (include_start_and_end) {
+ ow->StartObject(name);
+ }
+ while (tag != end_tag) {
+ if (tag != last_tag) { // Update field only if tag is changed.
+ last_tag = tag;
+ field = FindAndVerifyField(type, tag);
+ if (field != NULL) {
+ field_name = field->name();
+ }
+ }
+ if (field == NULL) {
+ // If we didn't find a field, skip this unknown tag.
+ // TODO(wpoon): Check return boolean value.
+ WireFormat::SkipField(stream_, tag, NULL);
+ tag = stream_->ReadTag();
+ continue;
+ }
+
+ if (field->cardinality() ==
+ google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) {
+ if (IsMap(*field)) {
+ ow->StartObject(field_name);
+ ASSIGN_OR_RETURN(tag, RenderMap(field, field_name, tag, ow));
+ ow->EndObject();
+ } else {
+ ASSIGN_OR_RETURN(tag, RenderList(field, field_name, tag, ow));
+ }
+ } else {
+ // Render the field.
+ RETURN_IF_ERROR(RenderField(field, field_name, ow));
+ tag = stream_->ReadTag();
+ }
+ }
+ if (include_start_and_end) {
+ ow->EndObject();
+ }
+ return Status::OK;
+}
+
+StatusOr<uint32> ProtoStreamObjectSource::RenderList(
+ const google::protobuf::Field* field, StringPiece name, uint32 list_tag,
+ ObjectWriter* ow) const {
+ uint32 tag_to_return = 0;
+ ow->StartList(name);
+ if (IsPackable(*field) &&
+ list_tag ==
+ WireFormatLite::MakeTag(field->number(),
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) {
+ RETURN_IF_ERROR(RenderPacked(field, ow));
+ // Since packed fields have a single tag, read another tag from stream to
+ // return.
+ tag_to_return = stream_->ReadTag();
+ } else {
+ do {
+ RETURN_IF_ERROR(RenderField(field, "", ow));
+ } while ((tag_to_return = stream_->ReadTag()) == list_tag);
+ }
+ ow->EndList();
+ return tag_to_return;
+}
+
+StatusOr<uint32> ProtoStreamObjectSource::RenderMap(
+ const google::protobuf::Field* field, StringPiece name, uint32 list_tag,
+ ObjectWriter* ow) const {
+ const google::protobuf::Type* field_type =
+ typeinfo_->GetType(field->type_url());
+ uint32 tag_to_return = 0;
+ if (IsPackable(*field) &&
+ list_tag ==
+ WireFormatLite::MakeTag(field->number(),
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) {
+ RETURN_IF_ERROR(RenderPackedMapEntry(field_type, ow));
+ tag_to_return = stream_->ReadTag();
+ } else {
+ do {
+ RETURN_IF_ERROR(RenderMapEntry(field_type, ow));
+ } while ((tag_to_return = stream_->ReadTag()) == list_tag);
+ }
+ return tag_to_return;
+}
+
+Status ProtoStreamObjectSource::RenderMapEntry(
+ const google::protobuf::Type* type, ObjectWriter* ow) const {
+ uint32 buffer32;
+ stream_->ReadVarint32(&buffer32); // message length
+ int old_limit = stream_->PushLimit(buffer32);
+ string map_key;
+ for (uint32 tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) {
+ const google::protobuf::Field* field = FindAndVerifyField(*type, tag);
+ if (field == NULL) {
+ WireFormat::SkipField(stream_, tag, NULL);
+ continue;
+ }
+ // Map field numbers are key = 1 and value = 2
+ if (field->number() == 1) {
+ map_key = ReadFieldValueAsString(*field);
+ } else if (field->number() == 2) {
+ if (map_key.empty()) {
+ return Status(util::error::INTERNAL, "Map key must be non-empty");
+ }
+ // Disable case normalization for map keys as they are just data. We
+ // retain them intact.
+ ow->DisableCaseNormalizationForNextKey();
+ RETURN_IF_ERROR(RenderField(field, map_key, ow));
+ }
+ }
+ stream_->PopLimit(old_limit);
+
+ return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderPacked(
+ const google::protobuf::Field* field, ObjectWriter* ow) const {
+ uint32 length;
+ stream_->ReadVarint32(&length);
+ int old_limit = stream_->PushLimit(length);
+ while (stream_->BytesUntilLimit() > 0) {
+ RETURN_IF_ERROR(RenderField(field, StringPiece(), ow));
+ }
+ stream_->PopLimit(old_limit);
+ return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderPackedMapEntry(
+ const google::protobuf::Type* type, ObjectWriter* ow) const {
+ uint32 length;
+ stream_->ReadVarint32(&length);
+ int old_limit = stream_->PushLimit(length);
+ while (stream_->BytesUntilLimit() > 0) {
+ RETURN_IF_ERROR(RenderMapEntry(type, ow));
+ }
+ stream_->PopLimit(old_limit);
+ return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderTimestamp(
+ const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+ StringPiece field_name, ObjectWriter* ow) {
+ pair<int64, int32> p = os->ReadSecondsAndNanos(type);
+ int64 seconds = p.first;
+ int32 nanos = p.second;
+ if (seconds > kMaxSeconds || seconds < kMinSeconds) {
+ return Status(
+ util::error::INTERNAL,
+ StrCat("Timestamp seconds exceeds limit for field: ", field_name));
+ }
+
+ if (nanos < 0 || nanos >= kNanosPerSecond) {
+ return Status(
+ util::error::INTERNAL,
+ StrCat("Timestamp nanos exceeds limit for field: ", field_name));
+ }
+
+ ow->RenderString(field_name,
+ ::google::protobuf::internal::FormatTime(seconds, nanos));
+
+ return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderDuration(
+ const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+ StringPiece field_name, ObjectWriter* ow) {
+ pair<int64, int32> p = os->ReadSecondsAndNanos(type);
+ int64 seconds = p.first;
+ int32 nanos = p.second;
+ if (seconds > kMaxSeconds || seconds < kMinSeconds) {
+ return Status(
+ util::error::INTERNAL,
+ StrCat("Duration seconds exceeds limit for field: ", field_name));
+ }
+
+ if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
+ return Status(
+ util::error::INTERNAL,
+ StrCat("Duration nanos exceeds limit for field: ", field_name));
+ }
+
+ string sign = "";
+ if (seconds < 0) {
+ if (nanos > 0) {
+ return Status(util::error::INTERNAL,
+ StrCat(
+ "Duration nanos is non-negative, but seconds is "
+ "negative for field: ",
+ field_name));
+ }
+ sign = "-";
+ seconds = -seconds;
+ nanos = -nanos;
+ } else if (seconds == 0 && nanos < 0) {
+ sign = "-";
+ nanos = -nanos;
+ }
+ string formatted_duration = StringPrintf("%s%lld%ss", sign.c_str(), seconds,
+ FormatNanos(nanos).c_str());
+ ow->RenderString(field_name, formatted_duration);
+ return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderDouble(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece field_name,
+ ObjectWriter* ow) {
+ uint32 tag = os->stream_->ReadTag();
+ uint64 buffer64 = 0; // default value of Double wrapper value
+ if (tag != 0) {
+ os->stream_->ReadLittleEndian64(&buffer64);
+ os->stream_->ReadTag();
+ }
+ ow->RenderDouble(field_name, bit_cast<double>(buffer64));
+ return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderFloat(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece field_name,
+ ObjectWriter* ow) {
+ uint32 tag = os->stream_->ReadTag();
+ uint32 buffer32 = 0; // default value of Float wrapper value
+ if (tag != 0) {
+ os->stream_->ReadLittleEndian32(&buffer32);
+ os->stream_->ReadTag();
+ }
+ ow->RenderFloat(field_name, bit_cast<float>(buffer32));
+ return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderInt64(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece field_name,
+ ObjectWriter* ow) {
+ uint32 tag = os->stream_->ReadTag();
+ uint64 buffer64 = 0; // default value of Int64 wrapper value
+ if (tag != 0) {
+ os->stream_->ReadVarint64(&buffer64);
+ os->stream_->ReadTag();
+ }
+ ow->RenderInt64(field_name, bit_cast<int64>(buffer64));
+ return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderUInt64(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece field_name,
+ ObjectWriter* ow) {
+ uint32 tag = os->stream_->ReadTag();
+ uint64 buffer64 = 0; // default value of UInt64 wrapper value
+ if (tag != 0) {
+ os->stream_->ReadVarint64(&buffer64);
+ os->stream_->ReadTag();
+ }
+ ow->RenderUint64(field_name, bit_cast<uint64>(buffer64));
+ return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderInt32(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece field_name,
+ ObjectWriter* ow) {
+ uint32 tag = os->stream_->ReadTag();
+ uint32 buffer32 = 0; // default value of Int32 wrapper value
+ if (tag != 0) {
+ os->stream_->ReadVarint32(&buffer32);
+ os->stream_->ReadTag();
+ }
+ ow->RenderInt32(field_name, bit_cast<int32>(buffer32));
+ return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderUInt32(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece field_name,
+ ObjectWriter* ow) {
+ uint32 tag = os->stream_->ReadTag();
+ uint32 buffer32 = 0; // default value of UInt32 wrapper value
+ if (tag != 0) {
+ os->stream_->ReadVarint32(&buffer32);
+ os->stream_->ReadTag();
+ }
+ ow->RenderUint32(field_name, bit_cast<uint32>(buffer32));
+ return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderBool(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece field_name,
+ ObjectWriter* ow) {
+ uint32 tag = os->stream_->ReadTag();
+ uint64 buffer64 = 0; // results in 'false' value as default, which is the
+ // default value of Bool wrapper
+ if (tag != 0) {
+ os->stream_->ReadVarint64(&buffer64);
+ os->stream_->ReadTag();
+ }
+ ow->RenderBool(field_name, buffer64 != 0);
+ return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderString(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece field_name,
+ ObjectWriter* ow) {
+ uint32 tag = os->stream_->ReadTag();
+ uint32 buffer32;
+ string str; // default value of empty for String wrapper
+ if (tag != 0) {
+ os->stream_->ReadVarint32(&buffer32); // string size.
+ os->stream_->ReadString(&str, buffer32);
+ os->stream_->ReadTag();
+ }
+ ow->RenderString(field_name, str);
+ return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderBytes(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece field_name,
+ ObjectWriter* ow) {
+ uint32 tag = os->stream_->ReadTag();
+ uint32 buffer32;
+ string str;
+ if (tag != 0) {
+ os->stream_->ReadVarint32(&buffer32);
+ os->stream_->ReadString(&str, buffer32);
+ os->stream_->ReadTag();
+ }
+ ow->RenderBytes(field_name, str);
+ return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderStruct(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece field_name,
+ ObjectWriter* ow) {
+ const google::protobuf::Field* field = NULL;
+ uint32 tag = os->stream_->ReadTag();
+ ow->StartObject(field_name);
+ while (tag != 0) {
+ field = os->FindAndVerifyField(type, tag);
+ // google.protobuf.Struct has only one field that is a map. Hence we use
+ // RenderMap to render that field.
+ if (os->IsMap(*field)) {
+ ASSIGN_OR_RETURN(tag, os->RenderMap(field, field_name, tag, ow));
+ }
+ }
+ ow->EndObject();
+ return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderStructValue(
+ const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+ StringPiece field_name, ObjectWriter* ow) {
+ const google::protobuf::Field* field = NULL;
+ for (uint32 tag = os->stream_->ReadTag(); tag != 0;
+ tag = os->stream_->ReadTag()) {
+ field = os->FindAndVerifyField(type, tag);
+ if (field == NULL) {
+ WireFormat::SkipField(os->stream_, tag, NULL);
+ continue;
+ }
+ RETURN_IF_ERROR(os->RenderField(field, field_name, ow));
+ }
+ return Status::OK;
+}
+
+// TODO(skarvaje): Avoid code duplication of for loops and SkipField logic.
+Status ProtoStreamObjectSource::RenderStructListValue(
+ const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+ StringPiece field_name, ObjectWriter* ow) {
+ uint32 tag = os->stream_->ReadTag();
+
+ // Render empty list when we find empty ListValue message.
+ if (tag == 0) {
+ ow->StartList(field_name);
+ ow->EndList();
+ return Status::OK;
+ }
+
+ while (tag != 0) {
+ const google::protobuf::Field* field = os->FindAndVerifyField(type, tag);
+ if (field == NULL) {
+ WireFormat::SkipField(os->stream_, tag, NULL);
+ tag = os->stream_->ReadTag();
+ continue;
+ }
+ ASSIGN_OR_RETURN(tag, os->RenderList(field, field_name, tag, ow));
+ }
+ return Status::OK;
+}
+
+Status ProtoStreamObjectSource::RenderAny(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece field_name,
+ ObjectWriter* ow) {
+ // An Any is of the form { string type_url = 1; bytes value = 2; }
+ uint32 tag;
+ string type_url;
+ string value;
+
+ // First read out the type_url and value from the proto stream
+ for (tag = os->stream_->ReadTag(); tag != 0; tag = os->stream_->ReadTag()) {
+ const google::protobuf::Field* field = os->FindAndVerifyField(type, tag);
+ if (field == NULL) {
+ WireFormat::SkipField(os->stream_, tag, NULL);
+ continue;
+ }
+ // 'type_url' has field number of 1 and 'value' has field number 2
+ // //google/protobuf/any.proto
+ if (field->number() == 1) {
+ // read type_url
+ uint32 type_url_size;
+ os->stream_->ReadVarint32(&type_url_size);
+ os->stream_->ReadString(&type_url, type_url_size);
+ } else if (field->number() == 2) {
+ // read value
+ uint32 value_size;
+ os->stream_->ReadVarint32(&value_size);
+ os->stream_->ReadString(&value, value_size);
+ }
+ }
+
+ // If there is no value, we don't lookup the type, we just output it (if
+ // present). If both type and value are empty we output an empty object.
+ if (value.empty()) {
+ ow->StartObject(field_name);
+ if (!type_url.empty()) {
+ ow->RenderString("@type", type_url);
+ }
+ ow->EndObject();
+ return util::Status::OK;
+ }
+
+ // If there is a value but no type, we cannot render it, so report an error.
+ if (type_url.empty()) {
+ // TODO(sven): Add an external message once those are ready.
+ return util::Status(util::error::INTERNAL,
+ "Invalid Any, the type_url is missing.");
+ }
+
+ util::StatusOr<const google::protobuf::Type*> resolved_type =
+ os->typeinfo_->ResolveTypeUrl(type_url);
+
+ if (!resolved_type.ok()) {
+ // Convert into an internal error, since this means the backend gave us
+ // an invalid response (missing or invalid type information).
+ return util::Status(util::error::INTERNAL,
+ resolved_type.status().error_message());
+ }
+ // nested_type cannot be null at this time.
+ const google::protobuf::Type* nested_type = resolved_type.ValueOrDie();
+
+ // We know the type so we can render it. Recursively parse the nested stream
+ // using a nested ProtoStreamObjectSource using our nested type information.
+ google::protobuf::io::ArrayInputStream zero_copy_stream(value.data(), value.size());
+ google::protobuf::io::CodedInputStream in_stream(&zero_copy_stream);
+ ProtoStreamObjectSource nested_os(&in_stream, os->typeinfo_, *nested_type);
+
+ // We manually call start and end object here so we can inject the @type.
+ ow->StartObject(field_name);
+ ow->RenderString("@type", type_url);
+ util::Status result =
+ nested_os.WriteMessage(nested_os.type_, "value", 0, false, ow);
+ ow->EndObject();
+ return result;
+}
+
+Status ProtoStreamObjectSource::RenderFieldMask(
+ const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
+ StringPiece field_name, ObjectWriter* ow) {
+ string combined;
+ uint32 buffer32;
+ uint32 paths_field_tag = 0;
+ for (uint32 tag = os->stream_->ReadTag(); tag != 0;
+ tag = os->stream_->ReadTag()) {
+ if (paths_field_tag == 0) {
+ const google::protobuf::Field* field = os->FindAndVerifyField(type, tag);
+ if (field != NULL && field->number() == 1 &&
+ field->name() == "paths") {
+ paths_field_tag = tag;
+ }
+ }
+ if (paths_field_tag != tag) {
+ return util::Status(util::error::INTERNAL,
+ "Invalid FieldMask, unexpected field.");
+ }
+ string str;
+ os->stream_->ReadVarint32(&buffer32); // string size.
+ os->stream_->ReadString(&str, buffer32);
+ if (!combined.empty()) {
+ combined.append(",");
+ }
+ combined.append(ConvertFieldMaskPath(str, &ToCamelCase));
+ }
+ ow->RenderString(field_name, combined);
+ return Status::OK;
+}
+
+hash_map<string, ProtoStreamObjectSource::TypeRenderer>*
+ProtoStreamObjectSource::CreateRendererMap() {
+ hash_map<string, ProtoStreamObjectSource::TypeRenderer>* result =
+ new hash_map<string, ProtoStreamObjectSource::TypeRenderer>();
+ (*result)["google.protobuf.Timestamp"] =
+ &ProtoStreamObjectSource::RenderTimestamp;
+ (*result)["google.protobuf.Duration"] =
+ &ProtoStreamObjectSource::RenderDuration;
+ (*result)["google.protobuf.DoubleValue"] =
+ &ProtoStreamObjectSource::RenderDouble;
+ (*result)["google.protobuf.FloatValue"] =
+ &ProtoStreamObjectSource::RenderFloat;
+ (*result)["google.protobuf.Int64Value"] =
+ &ProtoStreamObjectSource::RenderInt64;
+ (*result)["google.protobuf.UInt64Value"] =
+ &ProtoStreamObjectSource::RenderUInt64;
+ (*result)["google.protobuf.Int32Value"] =
+ &ProtoStreamObjectSource::RenderInt32;
+ (*result)["google.protobuf.UInt32Value"] =
+ &ProtoStreamObjectSource::RenderUInt32;
+ (*result)["google.protobuf.BoolValue"] = &ProtoStreamObjectSource::RenderBool;
+ (*result)["google.protobuf.StringValue"] =
+ &ProtoStreamObjectSource::RenderString;
+ (*result)["google.protobuf.BytesValue"] =
+ &ProtoStreamObjectSource::RenderBytes;
+ (*result)["google.protobuf.Any"] = &ProtoStreamObjectSource::RenderAny;
+ (*result)["google.protobuf.Struct"] = &ProtoStreamObjectSource::RenderStruct;
+ (*result)["google.protobuf.Value"] =
+ &ProtoStreamObjectSource::RenderStructValue;
+ (*result)["google.protobuf.ListValue"] =
+ &ProtoStreamObjectSource::RenderStructListValue;
+ (*result)["google.protobuf.FieldMask"] =
+ &ProtoStreamObjectSource::RenderFieldMask;
+ return result;
+}
+
+// static
+ProtoStreamObjectSource::TypeRenderer*
+ProtoStreamObjectSource::FindTypeRenderer(const string& type_url) {
+ static hash_map<string, TypeRenderer>* renderers = CreateRendererMap();
+ return FindOrNull(*renderers, type_url);
+}
+
+Status ProtoStreamObjectSource::RenderField(
+ const google::protobuf::Field* field, StringPiece field_name,
+ ObjectWriter* ow) const {
+ switch (field->kind()) {
+ case google::protobuf::Field_Kind_TYPE_BOOL: {
+ uint64 buffer64;
+ stream_->ReadVarint64(&buffer64);
+ ow->RenderBool(field_name, buffer64 != 0);
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_INT32: {
+ uint32 buffer32;
+ stream_->ReadVarint32(&buffer32);
+ ow->RenderInt32(field_name, bit_cast<int32>(buffer32));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_INT64: {
+ uint64 buffer64;
+ stream_->ReadVarint64(&buffer64);
+ ow->RenderInt64(field_name, bit_cast<int64>(buffer64));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_UINT32: {
+ uint32 buffer32;
+ stream_->ReadVarint32(&buffer32);
+ ow->RenderUint32(field_name, bit_cast<uint32>(buffer32));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_UINT64: {
+ uint64 buffer64;
+ stream_->ReadVarint64(&buffer64);
+ ow->RenderUint64(field_name, bit_cast<uint64>(buffer64));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_SINT32: {
+ uint32 buffer32;
+ stream_->ReadVarint32(&buffer32);
+ ow->RenderInt32(field_name, WireFormatLite::ZigZagDecode32(buffer32));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_SINT64: {
+ uint64 buffer64;
+ stream_->ReadVarint64(&buffer64);
+ ow->RenderInt64(field_name, WireFormatLite::ZigZagDecode64(buffer64));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_SFIXED32: {
+ uint32 buffer32;
+ stream_->ReadLittleEndian32(&buffer32);
+ ow->RenderInt32(field_name, bit_cast<int32>(buffer32));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_SFIXED64: {
+ uint64 buffer64;
+ stream_->ReadLittleEndian64(&buffer64);
+ ow->RenderInt64(field_name, bit_cast<int64>(buffer64));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_FIXED32: {
+ uint32 buffer32;
+ stream_->ReadLittleEndian32(&buffer32);
+ ow->RenderUint32(field_name, bit_cast<uint32>(buffer32));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_FIXED64: {
+ uint64 buffer64;
+ stream_->ReadLittleEndian64(&buffer64);
+ ow->RenderUint64(field_name, bit_cast<uint64>(buffer64));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_FLOAT: {
+ uint32 buffer32;
+ stream_->ReadLittleEndian32(&buffer32);
+ ow->RenderFloat(field_name, bit_cast<float>(buffer32));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_DOUBLE: {
+ uint64 buffer64;
+ stream_->ReadLittleEndian64(&buffer64);
+ ow->RenderDouble(field_name, bit_cast<double>(buffer64));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_ENUM: {
+ uint32 buffer32;
+ stream_->ReadVarint32(&buffer32);
+
+ // If the field represents an explicit NULL value, render null.
+ if (field->type_url() == kStructNullValueTypeUrl) {
+ ow->RenderNull(field_name);
+ break;
+ }
+
+ // Get the nested enum type for this field.
+ // TODO(skarvaje): Avoid string manipulation. Find ways to speed this
+ // up.
+ const google::protobuf::Enum* en = typeinfo_->GetEnum(field->type_url());
+ // Lookup the name of the enum, and render that. Skips unknown enums.
+ if (en != NULL) {
+ const google::protobuf::EnumValue* enum_value =
+ FindEnumValueByNumber(*en, buffer32);
+ if (enum_value != NULL) {
+ ow->RenderString(field_name, enum_value->name());
+ }
+ } else {
+ GOOGLE_LOG(INFO) << "Unkown enum skipped: " << field->type_url();
+ }
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_STRING: {
+ uint32 buffer32;
+ string str;
+ stream_->ReadVarint32(&buffer32); // string size.
+ stream_->ReadString(&str, buffer32);
+ ow->RenderString(field_name, str);
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_BYTES: {
+ uint32 buffer32;
+ stream_->ReadVarint32(&buffer32); // bytes size.
+ string value;
+ stream_->ReadString(&value, buffer32);
+ ow->RenderBytes(field_name, value);
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_MESSAGE: {
+ uint32 buffer32;
+ stream_->ReadVarint32(&buffer32); // message length
+ int old_limit = stream_->PushLimit(buffer32);
+ // Get the nested message type for this field.
+ const google::protobuf::Type* type =
+ typeinfo_->GetType(field->type_url());
+ if (type == NULL) {
+ return Status(util::error::INTERNAL,
+ StrCat("Invalid configuration. Could not find the type: ",
+ field->type_url()));
+ }
+ RETURN_IF_ERROR(WriteMessage(*type, field_name, 0, true, ow));
+ if (!stream_->ConsumedEntireMessage()) {
+ return Status(util::error::INVALID_ARGUMENT,
+ "Nested protocol message not parsed in its entirety.");
+ }
+ stream_->PopLimit(old_limit);
+ break;
+ }
+ default:
+ break;
+ }
+ return Status::OK;
+}
+
+// TODO(skarvaje): Fix this to avoid code duplication.
+const string ProtoStreamObjectSource::ReadFieldValueAsString(
+ const google::protobuf::Field& field) const {
+ string result;
+ switch (field.kind()) {
+ case google::protobuf::Field_Kind_TYPE_BOOL: {
+ uint64 buffer64;
+ stream_->ReadVarint64(&buffer64);
+ result = buffer64 != 0 ? "true" : "false";
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_INT32: {
+ uint32 buffer32;
+ stream_->ReadVarint32(&buffer32);
+ result = SimpleItoa(bit_cast<int32>(buffer32));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_INT64: {
+ uint64 buffer64;
+ stream_->ReadVarint64(&buffer64);
+ result = SimpleItoa(bit_cast<int64>(buffer64));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_UINT32: {
+ uint32 buffer32;
+ stream_->ReadVarint32(&buffer32);
+ result = SimpleItoa(bit_cast<uint32>(buffer32));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_UINT64: {
+ uint64 buffer64;
+ stream_->ReadVarint64(&buffer64);
+ result = SimpleItoa(bit_cast<uint64>(buffer64));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_SINT32: {
+ uint32 buffer32;
+ stream_->ReadVarint32(&buffer32);
+ result = SimpleItoa(WireFormatLite::ZigZagDecode32(buffer32));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_SINT64: {
+ uint64 buffer64;
+ stream_->ReadVarint64(&buffer64);
+ result = SimpleItoa(WireFormatLite::ZigZagDecode64(buffer64));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_SFIXED32: {
+ uint32 buffer32;
+ stream_->ReadLittleEndian32(&buffer32);
+ result = SimpleItoa(bit_cast<int32>(buffer32));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_SFIXED64: {
+ uint64 buffer64;
+ stream_->ReadLittleEndian64(&buffer64);
+ result = SimpleItoa(bit_cast<int64>(buffer64));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_FIXED32: {
+ uint32 buffer32;
+ stream_->ReadLittleEndian32(&buffer32);
+ result = SimpleItoa(bit_cast<uint32>(buffer32));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_FIXED64: {
+ uint64 buffer64;
+ stream_->ReadLittleEndian64(&buffer64);
+ result = SimpleItoa(bit_cast<uint64>(buffer64));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_FLOAT: {
+ uint32 buffer32;
+ stream_->ReadLittleEndian32(&buffer32);
+ result = SimpleFtoa(bit_cast<float>(buffer32));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_DOUBLE: {
+ uint64 buffer64;
+ stream_->ReadLittleEndian64(&buffer64);
+ result = SimpleDtoa(bit_cast<double>(buffer64));
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_ENUM: {
+ uint32 buffer32;
+ stream_->ReadVarint32(&buffer32);
+ // Get the nested enum type for this field.
+ // TODO(skarvaje): Avoid string manipulation. Find ways to speed this
+ // up.
+ const google::protobuf::Enum* en = typeinfo_->GetEnum(field.type_url());
+ // Lookup the name of the enum, and render that. Skips unknown enums.
+ if (en != NULL) {
+ const google::protobuf::EnumValue* enum_value =
+ FindEnumValueByNumber(*en, buffer32);
+ if (enum_value != NULL) {
+ result = enum_value->name();
+ }
+ }
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_STRING: {
+ uint32 buffer32;
+ stream_->ReadVarint32(&buffer32); // string size.
+ stream_->ReadString(&result, buffer32);
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_BYTES: {
+ uint32 buffer32;
+ stream_->ReadVarint32(&buffer32); // bytes size.
+ stream_->ReadString(&result, buffer32);
+ break;
+ }
+ default:
+ break;
+ }
+ return result;
+}
+
+// Field is a map if it is a repeated message and it has an option "map_type".
+// TODO(skarvaje): Consider pre-computing the IsMap() into Field directly.
+bool ProtoStreamObjectSource::IsMap(
+ const google::protobuf::Field& field) const {
+ const google::protobuf::Type* field_type =
+ typeinfo_->GetType(field.type_url());
+
+ // TODO(xiaofeng): Unify option names.
+ return field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE &&
+ (GetBoolOptionOrDefault(field_type->options(),
+ "google.protobuf.MessageOptions.map_entry", false) ||
+ GetBoolOptionOrDefault(field_type->options(), "map_entry", false));
+}
+
+std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos(
+ const google::protobuf::Type& type) const {
+ uint64 seconds = 0;
+ uint32 nanos = 0;
+ uint32 tag = 0;
+ int64 signed_seconds = 0;
+ int64 signed_nanos = 0;
+
+ for (tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) {
+ const google::protobuf::Field* field = FindAndVerifyField(type, tag);
+ if (field == NULL) {
+ WireFormat::SkipField(stream_, tag, NULL);
+ continue;
+ }
+ // 'seconds' has field number of 1 and 'nanos' has field number 2
+ // //google/protobuf/timestamp.proto & duration.proto
+ if (field->number() == 1) {
+ // read seconds
+ stream_->ReadVarint64(&seconds);
+ signed_seconds = bit_cast<int64>(seconds);
+ } else if (field->number() == 2) {
+ // read nanos
+ stream_->ReadVarint32(&nanos);
+ signed_nanos = bit_cast<int32>(nanos);
+ }
+ }
+ return std::pair<int64, int32>(signed_seconds, signed_nanos);
+}
+
+namespace {
+// TODO(skarvaje): Speed this up by not doing a linear scan.
+const google::protobuf::Field* FindFieldByNumber(
+ const google::protobuf::Type& type, int number) {
+ for (int i = 0; i < type.fields_size(); ++i) {
+ if (type.fields(i).number() == number) {
+ return &type.fields(i);
+ }
+ }
+ return NULL;
+}
+
+// TODO(skarvaje): Replace FieldDescriptor by implementing IsTypePackable()
+// using tech Field.
+bool IsPackable(const google::protobuf::Field& field) {
+ return field.cardinality() ==
+ google::protobuf::Field_Cardinality_CARDINALITY_REPEATED &&
+ google::protobuf::FieldDescriptor::IsTypePackable(
+ static_cast<google::protobuf::FieldDescriptor::Type>(field.kind()));
+}
+
+// TODO(skarvaje): Speed this up by not doing a linear scan.
+const google::protobuf::EnumValue* FindEnumValueByNumber(
+ const google::protobuf::Enum& tech_enum, int number) {
+ for (int i = 0; i < tech_enum.enumvalue_size(); ++i) {
+ const google::protobuf::EnumValue& ev = tech_enum.enumvalue(i);
+ if (ev.number() == number) {
+ return &ev;
+ }
+ }
+ return NULL;
+}
+
+// TODO(skarvaje): Look into optimizing this by not doing computation on
+// double.
+const string FormatNanos(uint32 nanos) {
+ const char* format =
+ (nanos % 1000 != 0) ? "%.9f" : (nanos % 1000000 != 0) ? "%.6f" : "%.3f";
+ string formatted =
+ StringPrintf(format, static_cast<double>(nanos) / kNanosPerSecond);
+ // remove the leading 0 before decimal.
+ return formatted.substr(1);
+}
+} // namespace
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h
new file mode 100644
index 00000000..4a4e6bbf
--- /dev/null
+++ b/src/google/protobuf/util/internal/protostream_objectsource.h
@@ -0,0 +1,245 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__
+
+#include <functional>
+#include <google/protobuf/stubs/hash.h>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/type.pb.h>
+#include <google/protobuf/util/internal/object_source.h>
+#include <google/protobuf/util/internal/object_writer.h>
+#include <google/protobuf/util/internal/type_info.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/statusor.h>
+
+
+
+namespace google {
+namespace protobuf {
+class Field;
+class Type;
+} // namespace protobuf
+
+
+namespace protobuf {
+namespace util {
+namespace converter {
+
+class TypeInfo;
+
+// An ObjectSource that can parse a stream of bytes as a protocol buffer.
+// This implementation uses a tech Type for tag lookup.
+//
+// Sample usage: (suppose input is: string proto)
+// ArrayInputStream arr_stream(proto.data(), proto.size());
+// CodedInputStream in_stream(&arr_stream);
+// ProtoStreamObjectSource os(&in_stream, /*ServiceTypeInfo*/ typeinfo,
+// <your message google::protobuf::Type>);
+//
+// Status status = os.WriteTo(<some ObjectWriter>);
+class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
+ public:
+ ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream,
+ TypeResolver* type_resolver,
+ const google::protobuf::Type& type);
+
+ virtual ~ProtoStreamObjectSource();
+
+ virtual util::Status NamedWriteTo(StringPiece name, ObjectWriter* ow) const;
+
+ protected:
+ // Writes a proto2 Message to the ObjectWriter. When the given end_tag is
+ // found this method will complete, allowing it to be used for parsing both
+ // nested messages (end with 0) and nested groups (end with group end tag).
+ // The include_start_and_end parameter allows this method to be called when
+ // already inside of an object, and skip calling StartObject and EndObject.
+ virtual util::Status WriteMessage(const google::protobuf::Type& descriptor,
+ StringPiece name, const uint32 end_tag,
+ bool include_start_and_end,
+ ObjectWriter* ow) const;
+
+ private:
+ ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream,
+ TypeInfo* typeinfo,
+ const google::protobuf::Type& type);
+ // Function that renders a well known type with a modified behavior.
+ typedef util::Status (*TypeRenderer)(const ProtoStreamObjectSource*,
+ const google::protobuf::Type&,
+ StringPiece, ObjectWriter*);
+
+ // Looks up a field and verify its consistency with wire type in tag.
+ const google::protobuf::Field* FindAndVerifyField(
+ const google::protobuf::Type& type, uint32 tag) const;
+
+ // TODO(skarvaje): Mark these methods as non-const as they modify internal
+ // state (stream_).
+ //
+ // Renders a repeating field (packed or unpacked).
+ // Returns the next tag after reading all sequential repeating elements. The
+ // caller should use this tag before reading more tags from the stream.
+ util::StatusOr<uint32> RenderList(const google::protobuf::Field* field,
+ StringPiece name, uint32 list_tag,
+ ObjectWriter* ow) const;
+ // Renders a NWP map.
+ // Returns the next tag after reading all map entries. The caller should use
+ // this tag before reading more tags from the stream.
+ util::StatusOr<uint32> RenderMap(const google::protobuf::Field* field,
+ StringPiece name, uint32 list_tag,
+ ObjectWriter* ow) const;
+
+ // Renders an entry in a map, advancing stream pointers appropriately.
+ util::Status RenderMapEntry(const google::protobuf::Type* type,
+ ObjectWriter* ow) const;
+
+ // Renders a packed repeating field. A packed field is stored as:
+ // {tag length item1 item2 item3} instead of the less efficient
+ // {tag item1 tag item2 tag item3}.
+ util::Status RenderPacked(const google::protobuf::Field* field,
+ ObjectWriter* ow) const;
+
+ // Equivalent of RenderPacked, but for map entries.
+ util::Status RenderPackedMapEntry(const google::protobuf::Type* type,
+ ObjectWriter* ow) const;
+
+ // Renders a google.protobuf.Timestamp value to ObjectWriter
+ static util::Status RenderTimestamp(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece name, ObjectWriter* ow);
+
+ // Renders a google.protobuf.Duration value to ObjectWriter
+ static util::Status RenderDuration(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece name, ObjectWriter* ow);
+
+ // Following RenderTYPE functions render well known types in
+ // google/protobuf/wrappers.proto corresponding to TYPE.
+ static util::Status RenderDouble(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece name, ObjectWriter* ow);
+ static util::Status RenderFloat(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece name, ObjectWriter* ow);
+ static util::Status RenderInt64(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece name, ObjectWriter* ow);
+ static util::Status RenderUInt64(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece name, ObjectWriter* ow);
+ static util::Status RenderInt32(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece name, ObjectWriter* ow);
+ static util::Status RenderUInt32(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece name, ObjectWriter* ow);
+ static util::Status RenderBool(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece name, ObjectWriter* ow);
+ static util::Status RenderString(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece name, ObjectWriter* ow);
+ static util::Status RenderBytes(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece name, ObjectWriter* ow);
+
+ // Renders a google.protobuf.Struct to ObjectWriter.
+ static util::Status RenderStruct(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece name, ObjectWriter* ow);
+
+ // Helper to render google.protobuf.Struct's Value fields to ObjectWriter.
+ static util::Status RenderStructValue(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece name, ObjectWriter* ow);
+
+ // Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter.
+ static util::Status RenderStructListValue(
+ const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece name, ObjectWriter* ow);
+
+ // Render the "Any" type.
+ static util::Status RenderAny(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece name, ObjectWriter* ow);
+
+ // Render the "FieldMask" type.
+ static util::Status RenderFieldMask(const ProtoStreamObjectSource* os,
+ const google::protobuf::Type& type,
+ StringPiece name, ObjectWriter* ow);
+
+ static hash_map<string, TypeRenderer>* CreateRendererMap();
+ static TypeRenderer* FindTypeRenderer(const string& type_url);
+
+ // Renders a field value to the ObjectWriter.
+ util::Status RenderField(const google::protobuf::Field* field,
+ StringPiece field_name, ObjectWriter* ow) const;
+
+ // Reads field value according to Field spec in 'field' and returns the read
+ // value as string. This only works for primitive datatypes (no message
+ // types).
+ const string ReadFieldValueAsString(
+ const google::protobuf::Field& field) const;
+
+ // Utility function to detect proto maps. The 'field' MUST be repeated.
+ bool IsMap(const google::protobuf::Field& field) const;
+
+ // Utility to read int64 and int32 values from a message type in stream_.
+ // Used for reading google.protobuf.Timestamp and Duration messages.
+ std::pair<int64, int32> ReadSecondsAndNanos(
+ const google::protobuf::Type& type) const;
+
+ // Input stream to read from. Ownership rests with the caller.
+ google::protobuf::io::CodedInputStream* stream_;
+
+ // Type information for all the types used in the descriptor. Used to find
+ // google::protobuf::Type of nested messages/enums.
+ TypeInfo* typeinfo_;
+ // Whether this class owns the typeinfo_ object. If true the typeinfo_ object
+ // should be deleted in the destructor.
+ bool own_typeinfo_;
+
+ // google::protobuf::Type of the message source.
+ const google::protobuf::Type& type_;
+
+ GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectSource);
+};
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__
diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
new file mode 100644
index 00000000..4cc62410
--- /dev/null
+++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
@@ -0,0 +1,824 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/protostream_objectsource.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <sstream>
+
+#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/any.pb.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/util/internal/expecting_objectwriter.h>
+#include <google/protobuf/util/internal/testdata/books.pb.h>
+#include <google/protobuf/util/internal/testdata/field_mask.pb.h>
+#include <google/protobuf/util/internal/type_info_test_helper.h>
+#include <google/protobuf/util/internal/constants.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/util/internal/testdata/anys.pb.h>
+#include <google/protobuf/util/internal/testdata/maps.pb.h>
+#include <google/protobuf/util/internal/testdata/struct.pb.h>
+#include <gtest/gtest.h>
+
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+using google::protobuf::Descriptor;
+using google::protobuf::DescriptorPool;
+using google::protobuf::FileDescriptorProto;
+using google::protobuf::Message;
+using google::protobuf::io::ArrayInputStream;
+using google::protobuf::io::CodedInputStream;
+using util::Status;
+using google::protobuf::testing::Author;
+using google::protobuf::testing::BadAuthor;
+using google::protobuf::testing::BadNestedBook;
+using google::protobuf::testing::Book;
+using google::protobuf::testing::Book_Label;
+using google::protobuf::testing::NestedBook;
+using google::protobuf::testing::PackedPrimitive;
+using google::protobuf::testing::Primitive;
+using google::protobuf::testing::more_author;
+using google::protobuf::testing::maps::MapOut;
+using google::protobuf::testing::anys::AnyOut;
+using google::protobuf::testing::anys::AnyM;
+using google::protobuf::testing::FieldMaskTest;
+using google::protobuf::testing::NestedFieldMask;
+using google::protobuf::testing::structs::StructType;
+using ::testing::_;
+
+
+namespace {
+string GetTypeUrl(const Descriptor* descriptor) {
+ return string(kTypeServiceBaseUrl) + "/" + descriptor->full_name();
+}
+} // namespace
+
+class ProtostreamObjectSourceTest
+ : public ::testing::TestWithParam<testing::TypeInfoSource> {
+ protected:
+ ProtostreamObjectSourceTest() : helper_(GetParam()), mock_(), ow_(&mock_) {
+ helper_.ResetTypeInfo(Book::descriptor());
+ }
+
+ virtual ~ProtostreamObjectSourceTest() {}
+
+ void DoTest(const Message& msg, const Descriptor* descriptor) {
+ Status status = ExecuteTest(msg, descriptor);
+ EXPECT_EQ(Status::OK, status);
+ }
+
+ Status ExecuteTest(const Message& msg, const Descriptor* descriptor) {
+ ostringstream oss;
+ msg.SerializePartialToOstream(&oss);
+ string proto = oss.str();
+ ArrayInputStream arr_stream(proto.data(), proto.size());
+ CodedInputStream in_stream(&arr_stream);
+
+ google::protobuf::scoped_ptr<ProtoStreamObjectSource> os(
+ helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor)));
+ return os->WriteTo(&mock_);
+ }
+
+ void PrepareExpectingObjectWriterForRepeatedPrimitive() {
+ ow_.StartObject("")
+ ->StartList("rep_fix32")
+ ->RenderUint32("", bit_cast<uint32>(3201))
+ ->RenderUint32("", bit_cast<uint32>(0))
+ ->RenderUint32("", bit_cast<uint32>(3202))
+ ->EndList()
+ ->StartList("rep_u32")
+ ->RenderUint32("", bit_cast<uint32>(3203))
+ ->RenderUint32("", bit_cast<uint32>(0))
+ ->EndList()
+ ->StartList("rep_i32")
+ ->RenderInt32("", 0)
+ ->RenderInt32("", 3204)
+ ->RenderInt32("", 3205)
+ ->EndList()
+ ->StartList("rep_sf32")
+ ->RenderInt32("", 3206)
+ ->RenderInt32("", 0)
+ ->EndList()
+ ->StartList("rep_s32")
+ ->RenderInt32("", 0)
+ ->RenderInt32("", 3207)
+ ->RenderInt32("", 3208)
+ ->EndList()
+ ->StartList("rep_fix64")
+ ->RenderUint64("", bit_cast<uint64>(6401LL))
+ ->RenderUint64("", bit_cast<uint64>(0LL))
+ ->EndList()
+ ->StartList("rep_u64")
+ ->RenderUint64("", bit_cast<uint64>(0LL))
+ ->RenderUint64("", bit_cast<uint64>(6402LL))
+ ->RenderUint64("", bit_cast<uint64>(6403LL))
+ ->EndList()
+ ->StartList("rep_i64")
+ ->RenderInt64("", 6404L)
+ ->RenderInt64("", 0L)
+ ->EndList()
+ ->StartList("rep_sf64")
+ ->RenderInt64("", 0L)
+ ->RenderInt64("", 6405L)
+ ->RenderInt64("", 6406L)
+ ->EndList()
+ ->StartList("rep_s64")
+ ->RenderInt64("", 6407L)
+ ->RenderInt64("", 0L)
+ ->EndList()
+ ->StartList("rep_float")
+ ->RenderFloat("", 0.0f)
+ ->RenderFloat("", 32.1f)
+ ->RenderFloat("", 32.2f)
+ ->EndList()
+ ->StartList("rep_double")
+ ->RenderDouble("", 64.1L)
+ ->RenderDouble("", 0.0L)
+ ->EndList()
+ ->StartList("rep_bool")
+ ->RenderBool("", true)
+ ->RenderBool("", false)
+ ->EndList()
+ ->EndObject();
+ }
+
+ Primitive PrepareRepeatedPrimitive() {
+ Primitive primitive;
+ primitive.add_rep_fix32(3201);
+ primitive.add_rep_fix32(0);
+ primitive.add_rep_fix32(3202);
+ primitive.add_rep_u32(3203);
+ primitive.add_rep_u32(0);
+ primitive.add_rep_i32(0);
+ primitive.add_rep_i32(3204);
+ primitive.add_rep_i32(3205);
+ primitive.add_rep_sf32(3206);
+ primitive.add_rep_sf32(0);
+ primitive.add_rep_s32(0);
+ primitive.add_rep_s32(3207);
+ primitive.add_rep_s32(3208);
+ primitive.add_rep_fix64(6401L);
+ primitive.add_rep_fix64(0L);
+ primitive.add_rep_u64(0L);
+ primitive.add_rep_u64(6402L);
+ primitive.add_rep_u64(6403L);
+ primitive.add_rep_i64(6404L);
+ primitive.add_rep_i64(0L);
+ primitive.add_rep_sf64(0L);
+ primitive.add_rep_sf64(6405L);
+ primitive.add_rep_sf64(6406L);
+ primitive.add_rep_s64(6407L);
+ primitive.add_rep_s64(0L);
+ primitive.add_rep_float(0.0f);
+ primitive.add_rep_float(32.1f);
+ primitive.add_rep_float(32.2f);
+ primitive.add_rep_double(64.1L);
+ primitive.add_rep_double(0.0);
+ primitive.add_rep_bool(true);
+ primitive.add_rep_bool(false);
+
+ PrepareExpectingObjectWriterForRepeatedPrimitive();
+ return primitive;
+ }
+
+ PackedPrimitive PreparePackedPrimitive() {
+ PackedPrimitive primitive;
+ primitive.add_rep_fix32(3201);
+ primitive.add_rep_fix32(0);
+ primitive.add_rep_fix32(3202);
+ primitive.add_rep_u32(3203);
+ primitive.add_rep_u32(0);
+ primitive.add_rep_i32(0);
+ primitive.add_rep_i32(3204);
+ primitive.add_rep_i32(3205);
+ primitive.add_rep_sf32(3206);
+ primitive.add_rep_sf32(0);
+ primitive.add_rep_s32(0);
+ primitive.add_rep_s32(3207);
+ primitive.add_rep_s32(3208);
+ primitive.add_rep_fix64(6401L);
+ primitive.add_rep_fix64(0L);
+ primitive.add_rep_u64(0L);
+ primitive.add_rep_u64(6402L);
+ primitive.add_rep_u64(6403L);
+ primitive.add_rep_i64(6404L);
+ primitive.add_rep_i64(0L);
+ primitive.add_rep_sf64(0L);
+ primitive.add_rep_sf64(6405L);
+ primitive.add_rep_sf64(6406L);
+ primitive.add_rep_s64(6407L);
+ primitive.add_rep_s64(0L);
+ primitive.add_rep_float(0.0f);
+ primitive.add_rep_float(32.1f);
+ primitive.add_rep_float(32.2f);
+ primitive.add_rep_double(64.1L);
+ primitive.add_rep_double(0.0);
+ primitive.add_rep_bool(true);
+ primitive.add_rep_bool(false);
+
+ PrepareExpectingObjectWriterForRepeatedPrimitive();
+ return primitive;
+ }
+
+ testing::TypeInfoTestHelper helper_;
+
+ ::testing::NiceMock<MockObjectWriter> mock_;
+ ExpectingObjectWriter ow_;
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+ ProtostreamObjectSourceTest,
+ ::testing::Values(
+ testing::USE_TYPE_RESOLVER));
+
+TEST_P(ProtostreamObjectSourceTest, EmptyMessage) {
+ Book empty;
+ ow_.StartObject("")->EndObject();
+ DoTest(empty, Book::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, Primitives) {
+ Primitive primitive;
+ primitive.set_fix32(3201);
+ primitive.set_u32(3202);
+ primitive.set_i32(3203);
+ primitive.set_sf32(3204);
+ primitive.set_s32(3205);
+ primitive.set_fix64(6401L);
+ primitive.set_u64(6402L);
+ primitive.set_i64(6403L);
+ primitive.set_sf64(6404L);
+ primitive.set_s64(6405L);
+ primitive.set_str("String Value");
+ primitive.set_bytes("Some Bytes");
+ primitive.set_float_(32.1f);
+ primitive.set_double_(64.1L);
+ primitive.set_bool_(true);
+
+ ow_.StartObject("")
+ ->RenderUint32("fix32", bit_cast<uint32>(3201))
+ ->RenderUint32("u32", bit_cast<uint32>(3202))
+ ->RenderInt32("i32", 3203)
+ ->RenderInt32("sf32", 3204)
+ ->RenderInt32("s32", 3205)
+ ->RenderUint64("fix64", bit_cast<uint64>(6401LL))
+ ->RenderUint64("u64", bit_cast<uint64>(6402LL))
+ ->RenderInt64("i64", 6403L)
+ ->RenderInt64("sf64", 6404L)
+ ->RenderInt64("s64", 6405L)
+ ->RenderString("str", "String Value")
+ ->RenderBytes("bytes", "Some Bytes")
+ ->RenderFloat("float", 32.1f)
+ ->RenderDouble("double", 64.1L)
+ ->RenderBool("bool", true)
+ ->EndObject();
+ DoTest(primitive, Primitive::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, RepeatingPrimitives) {
+ Primitive primitive = PrepareRepeatedPrimitive();
+ primitive.add_rep_str("String One");
+ primitive.add_rep_str("String Two");
+ primitive.add_rep_bytes("Some Bytes");
+
+ ow_.StartList("rep_str")
+ ->RenderString("", "String One")
+ ->RenderString("", "String Two")
+ ->EndList()
+ ->StartList("rep_bytes")
+ ->RenderBytes("", "Some Bytes")
+ ->EndList();
+ DoTest(primitive, Primitive::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, NestedMessage) {
+ Author* author = new Author();
+ author->set_id(101L);
+ author->set_name("Tolstoy");
+ Book book;
+ book.set_title("My Book");
+ book.set_allocated_author(author);
+
+ ow_.StartObject("")
+ ->RenderString("title", "My Book")
+ ->StartObject("author")
+ ->RenderUint64("id", bit_cast<uint64>(101LL))
+ ->RenderString("name", "Tolstoy")
+ ->EndObject()
+ ->EndObject();
+ DoTest(book, Book::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, RepeatingField) {
+ Author author;
+ author.set_alive(false);
+ author.set_name("john");
+ author.add_pseudonym("phil");
+ author.add_pseudonym("bob");
+
+ ow_.StartObject("")
+ ->RenderBool("alive", false)
+ ->RenderString("name", "john")
+ ->StartList("pseudonym")
+ ->RenderString("", "phil")
+ ->RenderString("", "bob")
+ ->EndList()
+ ->EndObject();
+ DoTest(author, Author::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, PackedRepeatingFields) {
+ DoTest(PreparePackedPrimitive(), PackedPrimitive::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, NonPackedPackableFieldsActuallyPacked) {
+ // Protostream is packed, but parse with non-packed Primitive.
+ DoTest(PreparePackedPrimitive(), Primitive::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, PackedPackableFieldNotActuallyPacked) {
+ // Protostream is not packed, but parse with PackedPrimitive.
+ DoTest(PrepareRepeatedPrimitive(), PackedPrimitive::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, BadAuthor) {
+ Author author;
+ author.set_alive(false);
+ author.set_name("john");
+ author.set_id(1234L);
+ author.add_pseudonym("phil");
+ author.add_pseudonym("bob");
+
+ ow_.StartObject("")
+ ->StartList("alive")
+ ->RenderBool("", false)
+ ->EndList()
+ ->StartList("name")
+ ->RenderUint64("", static_cast<uint64>('j'))
+ ->RenderUint64("", static_cast<uint64>('o'))
+ ->RenderUint64("", static_cast<uint64>('h'))
+ ->RenderUint64("", static_cast<uint64>('n'))
+ ->EndList()
+ ->RenderString("pseudonym", "phil")
+ ->RenderString("pseudonym", "bob")
+ ->EndObject();
+ // Protostream created with Author, but parsed with BadAuthor.
+ DoTest(author, BadAuthor::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, NestedBookToBadNestedBook) {
+ Book* book = new Book();
+ book->set_length(250);
+ book->set_published(2014L);
+ NestedBook nested;
+ nested.set_allocated_book(book);
+
+ ow_.StartObject("")
+ ->StartList("book")
+ ->RenderUint32("", 24) // tag for field length (3 << 3)
+ ->RenderUint32("", 250)
+ ->RenderUint32("", 32) // tag for field published (4 << 3)
+ ->RenderUint32("", 2014)
+ ->EndList()
+ ->EndObject();
+ // Protostream created with NestedBook, but parsed with BadNestedBook.
+ DoTest(nested, BadNestedBook::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, BadNestedBookToNestedBook) {
+ BadNestedBook nested;
+ nested.add_book(1);
+ nested.add_book(2);
+ nested.add_book(3);
+ nested.add_book(4);
+ nested.add_book(5);
+ nested.add_book(6);
+ nested.add_book(7);
+
+ ow_.StartObject("")->StartObject("book")->EndObject()->EndObject();
+ // Protostream created with BadNestedBook, but parsed with NestedBook.
+ DoTest(nested, NestedBook::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest,
+ LongRepeatedListDoesNotBreakIntoMultipleJsonLists) {
+ Book book;
+
+ int repeat = 10000;
+ for (int i = 0; i < repeat; ++i) {
+ Book_Label* label = book.add_labels();
+ label->set_key(StrCat("i", i));
+ label->set_value(StrCat("v", i));
+ }
+
+ // Make sure StartList and EndList are called exactly once (see b/18227499 for
+ // problems when this doesn't happen)
+ EXPECT_CALL(mock_, StartList(_)).Times(1);
+ EXPECT_CALL(mock_, EndList()).Times(1);
+
+ DoTest(book, Book::descriptor());
+}
+
+class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest {
+ protected:
+ ProtostreamObjectSourceMapsTest() {
+ helper_.ResetTypeInfo(MapOut::descriptor());
+ }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+ ProtostreamObjectSourceMapsTest,
+ ::testing::Values(
+ testing::USE_TYPE_RESOLVER));
+
+// Tests JSON map.
+//
+// This is the example expected output.
+// {
+// "map1": {
+// "key1": {
+// "foo": "foovalue"
+// },
+// "key2": {
+// "foo": "barvalue"
+// }
+// },
+// "map2": {
+// "nestedself": {
+// "map1": {
+// "nested_key1": {
+// "foo": "nested_foo"
+// }
+// },
+// "bar": "nested_bar_string"
+// }
+// },
+// "map3": {
+// "111": "one one one"
+// },
+// "bar": "top bar"
+// }
+TEST_P(ProtostreamObjectSourceMapsTest, MapsTest) {
+ MapOut out;
+ (*out.mutable_map1())["key1"].set_foo("foovalue");
+ (*out.mutable_map1())["key2"].set_foo("barvalue");
+
+ MapOut* nested_value = &(*out.mutable_map2())["nestedself"];
+ (*nested_value->mutable_map1())["nested_key1"].set_foo("nested_foo");
+ nested_value->set_bar("nested_bar_string");
+
+ (*out.mutable_map3())[111] = "one one one";
+
+ out.set_bar("top bar");
+
+ ow_.StartObject("")
+ ->StartObject("map1")
+ ->StartObject("key1")
+ ->RenderString("foo", "foovalue")
+ ->EndObject()
+ ->StartObject("key2")
+ ->RenderString("foo", "barvalue")
+ ->EndObject()
+ ->StartObject("map2")
+ ->StartObject("nestedself")
+ ->StartObject("map1")
+ ->StartObject("nested_key1")
+ ->RenderString("foo", "nested_foo")
+ ->EndObject()
+ ->EndObject()
+ ->RenderString("bar", "nested_bar_string")
+ ->EndObject()
+ ->EndObject()
+ ->StartObject("map3")
+ ->RenderString("111", "one one one")
+ ->EndObject()
+ ->EndObject()
+ ->RenderString("bar", "top bar")
+ ->EndObject();
+
+ DoTest(out, MapOut::descriptor());
+}
+
+class ProtostreamObjectSourceAnysTest : public ProtostreamObjectSourceTest {
+ protected:
+ ProtostreamObjectSourceAnysTest() {
+ helper_.ResetTypeInfo(AnyOut::descriptor(),
+ google::protobuf::Any::descriptor());
+ }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+ ProtostreamObjectSourceAnysTest,
+ ::testing::Values(
+ testing::USE_TYPE_RESOLVER));
+
+// Tests JSON any support.
+//
+// This is the example expected output.
+// {
+// "any": {
+// "@type": "type.googleapis.com/google.protobuf.testing.anys.AnyM"
+// "foo": "foovalue"
+// }
+// }
+TEST_P(ProtostreamObjectSourceAnysTest, BasicAny) {
+ AnyOut out;
+ ::google::protobuf::Any* any = out.mutable_any();
+
+ AnyM m;
+ m.set_foo("foovalue");
+ any->PackFrom(m);
+
+ ow_.StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type",
+ "type.googleapis.com/google.protobuf.testing.anys.AnyM")
+ ->RenderString("foo", "foovalue")
+ ->EndObject()
+ ->EndObject();
+
+ DoTest(out, AnyOut::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceAnysTest, RecursiveAny) {
+ AnyOut out;
+ ::google::protobuf::Any* any = out.mutable_any();
+ any->set_type_url("type.googleapis.com/google.protobuf.Any");
+
+ ::google::protobuf::Any nested_any;
+ nested_any.set_type_url(
+ "type.googleapis.com/google.protobuf.testing.anys.AnyM");
+
+ AnyM m;
+ m.set_foo("foovalue");
+ nested_any.set_value(m.SerializeAsString());
+
+ any->set_value(nested_any.SerializeAsString());
+
+ ow_.StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
+ ->StartObject("value")
+ ->RenderString("@type",
+ "type.googleapis.com/google.protobuf.testing.anys.AnyM")
+ ->RenderString("foo", "foovalue")
+ ->EndObject()
+ ->EndObject()
+ ->EndObject();
+
+ DoTest(out, AnyOut::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceAnysTest, DoubleRecursiveAny) {
+ AnyOut out;
+ ::google::protobuf::Any* any = out.mutable_any();
+ any->set_type_url("type.googleapis.com/google.protobuf.Any");
+
+ ::google::protobuf::Any nested_any;
+ nested_any.set_type_url("type.googleapis.com/google.protobuf.Any");
+
+ ::google::protobuf::Any second_nested_any;
+ second_nested_any.set_type_url(
+ "type.googleapis.com/google.protobuf.testing.anys.AnyM");
+
+ AnyM m;
+ m.set_foo("foovalue");
+ second_nested_any.set_value(m.SerializeAsString());
+ nested_any.set_value(second_nested_any.SerializeAsString());
+ any->set_value(nested_any.SerializeAsString());
+
+ ow_.StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
+ ->StartObject("value")
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
+ ->StartObject("value")
+ ->RenderString("@type",
+ "type.googleapis.com/google.protobuf.testing.anys.AnyM")
+ ->RenderString("foo", "foovalue")
+ ->EndObject()
+ ->EndObject()
+ ->EndObject()
+ ->EndObject();
+
+ DoTest(out, AnyOut::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceAnysTest, EmptyAnyOutputsEmptyObject) {
+ AnyOut out;
+ out.mutable_any();
+
+ ow_.StartObject("")->StartObject("any")->EndObject()->EndObject();
+
+ DoTest(out, AnyOut::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceAnysTest, EmptyWithTypeAndNoValueOutputsType) {
+ AnyOut out;
+ out.mutable_any()->set_type_url("foo.googleapis.com/my.Type");
+
+ ow_.StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "foo.googleapis.com/my.Type")
+ ->EndObject()
+ ->EndObject();
+
+ DoTest(out, AnyOut::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceAnysTest, MissingTypeUrlError) {
+ AnyOut out;
+ ::google::protobuf::Any* any = out.mutable_any();
+
+ AnyM m;
+ m.set_foo("foovalue");
+ any->set_value(m.SerializeAsString());
+
+ // We start the "AnyOut" part and then fail when we hit the Any object.
+ ow_.StartObject("");
+
+ Status status = ExecuteTest(out, AnyOut::descriptor());
+ EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
+TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeServiceError) {
+ AnyOut out;
+ ::google::protobuf::Any* any = out.mutable_any();
+ any->set_type_url("foo.googleapis.com/my.own.Type");
+
+ AnyM m;
+ m.set_foo("foovalue");
+ any->set_value(m.SerializeAsString());
+
+ // We start the "AnyOut" part and then fail when we hit the Any object.
+ ow_.StartObject("");
+
+ Status status = ExecuteTest(out, AnyOut::descriptor());
+ EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
+TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeError) {
+ AnyOut out;
+ ::google::protobuf::Any* any = out.mutable_any();
+ any->set_type_url("type.googleapis.com/unknown.Type");
+
+ AnyM m;
+ m.set_foo("foovalue");
+ any->set_value(m.SerializeAsString());
+
+ // We start the "AnyOut" part and then fail when we hit the Any object.
+ ow_.StartObject("");
+
+ Status status = ExecuteTest(out, AnyOut::descriptor());
+ EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
+class ProtostreamObjectSourceStructTest : public ProtostreamObjectSourceTest {
+ protected:
+ ProtostreamObjectSourceStructTest() {
+ helper_.ResetTypeInfo(StructType::descriptor(),
+ google::protobuf::Struct::descriptor());
+ }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+ ProtostreamObjectSourceStructTest,
+ ::testing::Values(
+ testing::USE_TYPE_RESOLVER));
+
+// Tests struct
+//
+// "object": {
+// "k1": 123,
+// "k2": true
+// }
+TEST_P(ProtostreamObjectSourceStructTest, StructRenderSuccess) {
+ StructType out;
+ google::protobuf::Struct* s = out.mutable_object();
+ s->mutable_fields()->operator[]("k1").set_number_value(123);
+ s->mutable_fields()->operator[]("k2").set_bool_value(true);
+
+ ow_.StartObject("")
+ ->StartObject("object")
+ ->RenderDouble("k1", 123)
+ ->RenderBool("k2", true)
+ ->EndObject()
+ ->EndObject();
+
+ DoTest(out, StructType::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceStructTest, MissingValueSkipsField) {
+ StructType out;
+ google::protobuf::Struct* s = out.mutable_object();
+ s->mutable_fields()->operator[]("k1");
+
+ ow_.StartObject("")->StartObject("object")->EndObject()->EndObject();
+
+ DoTest(out, StructType::descriptor());
+}
+
+class ProtostreamObjectSourceFieldMaskTest
+ : public ProtostreamObjectSourceTest {
+ protected:
+ ProtostreamObjectSourceFieldMaskTest() {
+ helper_.ResetTypeInfo(FieldMaskTest::descriptor(),
+ google::protobuf::FieldMask::descriptor());
+ }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+ ProtostreamObjectSourceFieldMaskTest,
+ ::testing::Values(
+ testing::USE_TYPE_RESOLVER));
+
+TEST_P(ProtostreamObjectSourceFieldMaskTest, FieldMaskRenderSuccess) {
+ FieldMaskTest out;
+ out.set_id("1");
+ out.mutable_single_mask()->add_paths("path1");
+ out.mutable_single_mask()->add_paths("snake_case_path2");
+ ::google::protobuf::FieldMask* mask = out.add_repeated_mask();
+ mask->add_paths("path3");
+ mask = out.add_repeated_mask();
+ mask->add_paths("snake_case_path4");
+ mask->add_paths("path5");
+ NestedFieldMask* nested = out.add_nested_mask();
+ nested->set_data("data");
+ nested->mutable_single_mask()->add_paths("nested.path1");
+ nested->mutable_single_mask()->add_paths("nested_field.snake_case_path2");
+ mask = nested->add_repeated_mask();
+ mask->add_paths("nested_field.path3");
+ mask->add_paths("nested.snake_case_path4");
+ mask = nested->add_repeated_mask();
+ mask->add_paths("nested.path5");
+ mask = nested->add_repeated_mask();
+ mask->add_paths(
+ "snake_case.map_field[\"map_key_should_be_ignored\"].nested_snake_case."
+ "map_field[\"map_key_sho\\\"uld_be_ignored\"]");
+
+ ow_.StartObject("")
+ ->RenderString("id", "1")
+ ->RenderString("single_mask", "path1,snakeCasePath2")
+ ->StartList("repeated_mask")
+ ->RenderString("", "path3")
+ ->RenderString("", "snakeCasePath4,path5")
+ ->EndList()
+ ->StartList("nested_mask")
+ ->StartObject("")
+ ->RenderString("data", "data")
+ ->RenderString("single_mask", "nested.path1,nestedField.snakeCasePath2")
+ ->StartList("repeated_mask")
+ ->RenderString("", "nestedField.path3,nested.snakeCasePath4")
+ ->RenderString("", "nested.path5")
+ ->RenderString("",
+ "snakeCase.mapField[\"map_key_should_be_ignored\"]."
+ "nestedSnakeCase.mapField[\"map_key_sho\\\"uld_be_"
+ "ignored\"]")
+ ->EndList()
+ ->EndObject()
+ ->EndList()
+ ->EndObject();
+
+ DoTest(out, FieldMaskTest::descriptor());
+}
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
new file mode 100644
index 00000000..f9ddbf32
--- /dev/null
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -0,0 +1,1557 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/protostream_objectwriter.h>
+
+#include <functional>
+#include <stack>
+
+#include <google/protobuf/stubs/time.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/util/internal/field_mask_utility.h>
+#include <google/protobuf/util/internal/object_location_tracker.h>
+#include <google/protobuf/util/internal/constants.h>
+#include <google/protobuf/util/internal/utility.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/statusor.h>
+
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+using google::protobuf::internal::WireFormatLite;
+using google::protobuf::io::CodedOutputStream;
+using util::error::INVALID_ARGUMENT;
+using util::Status;
+using util::StatusOr;
+
+
+ProtoStreamObjectWriter::ProtoStreamObjectWriter(
+ TypeResolver* type_resolver, const google::protobuf::Type& type,
+ strings::ByteSink* output, ErrorListener* listener)
+ : master_type_(type),
+ typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
+ own_typeinfo_(true),
+ done_(false),
+ element_(NULL),
+ size_insert_(),
+ output_(output),
+ buffer_(),
+ adapter_(&buffer_),
+ stream_(new CodedOutputStream(&adapter_)),
+ listener_(listener),
+ invalid_depth_(0),
+ tracker_(new ObjectLocationTracker()) {}
+
+ProtoStreamObjectWriter::ProtoStreamObjectWriter(
+ TypeInfo* typeinfo, const google::protobuf::Type& type,
+ strings::ByteSink* output, ErrorListener* listener)
+ : master_type_(type),
+ typeinfo_(typeinfo),
+ own_typeinfo_(false),
+ done_(false),
+ element_(NULL),
+ size_insert_(),
+ output_(output),
+ buffer_(),
+ adapter_(&buffer_),
+ stream_(new CodedOutputStream(&adapter_)),
+ listener_(listener),
+ invalid_depth_(0),
+ tracker_(new ObjectLocationTracker()) {}
+
+ProtoStreamObjectWriter::~ProtoStreamObjectWriter() {
+ // Cleanup explicitly in order to avoid destructor stack overflow when input
+ // is deeply nested.
+ while (element_ != NULL) {
+ element_.reset(element_->pop());
+ }
+ if (own_typeinfo_) {
+ delete typeinfo_;
+ }
+}
+
+namespace {
+
+// Writes an INT32 field, including tag to the stream.
+inline Status WriteInt32(int field_number, const DataPiece& data,
+ CodedOutputStream* stream) {
+ StatusOr<int32> i32 = data.ToInt32();
+ if (i32.ok()) {
+ WireFormatLite::WriteInt32(field_number, i32.ValueOrDie(), stream);
+ }
+ return i32.status();
+}
+
+// writes an SFIXED32 field, including tag, to the stream.
+inline Status WriteSFixed32(int field_number, const DataPiece& data,
+ CodedOutputStream* stream) {
+ StatusOr<int32> i32 = data.ToInt32();
+ if (i32.ok()) {
+ WireFormatLite::WriteSFixed32(field_number, i32.ValueOrDie(), stream);
+ }
+ return i32.status();
+}
+
+// Writes an SINT32 field, including tag, to the stream.
+inline Status WriteSInt32(int field_number, const DataPiece& data,
+ CodedOutputStream* stream) {
+ StatusOr<int32> i32 = data.ToInt32();
+ if (i32.ok()) {
+ WireFormatLite::WriteSInt32(field_number, i32.ValueOrDie(), stream);
+ }
+ return i32.status();
+}
+
+// Writes a FIXED32 field, including tag, to the stream.
+inline Status WriteFixed32(int field_number, const DataPiece& data,
+ CodedOutputStream* stream) {
+ StatusOr<uint32> u32 = data.ToUint32();
+ if (u32.ok()) {
+ WireFormatLite::WriteFixed32(field_number, u32.ValueOrDie(), stream);
+ }
+ return u32.status();
+}
+
+// Writes a UINT32 field, including tag, to the stream.
+inline Status WriteUInt32(int field_number, const DataPiece& data,
+ CodedOutputStream* stream) {
+ StatusOr<uint32> u32 = data.ToUint32();
+ if (u32.ok()) {
+ WireFormatLite::WriteUInt32(field_number, u32.ValueOrDie(), stream);
+ }
+ return u32.status();
+}
+
+// Writes an INT64 field, including tag, to the stream.
+inline Status WriteInt64(int field_number, const DataPiece& data,
+ CodedOutputStream* stream) {
+ StatusOr<int64> i64 = data.ToInt64();
+ if (i64.ok()) {
+ WireFormatLite::WriteInt64(field_number, i64.ValueOrDie(), stream);
+ }
+ return i64.status();
+}
+
+// Writes an SFIXED64 field, including tag, to the stream.
+inline Status WriteSFixed64(int field_number, const DataPiece& data,
+ CodedOutputStream* stream) {
+ StatusOr<int64> i64 = data.ToInt64();
+ if (i64.ok()) {
+ WireFormatLite::WriteSFixed64(field_number, i64.ValueOrDie(), stream);
+ }
+ return i64.status();
+}
+
+// Writes an SINT64 field, including tag, to the stream.
+inline Status WriteSInt64(int field_number, const DataPiece& data,
+ CodedOutputStream* stream) {
+ StatusOr<int64> i64 = data.ToInt64();
+ if (i64.ok()) {
+ WireFormatLite::WriteSInt64(field_number, i64.ValueOrDie(), stream);
+ }
+ return i64.status();
+}
+
+// Writes a FIXED64 field, including tag, to the stream.
+inline Status WriteFixed64(int field_number, const DataPiece& data,
+ CodedOutputStream* stream) {
+ StatusOr<uint64> u64 = data.ToUint64();
+ if (u64.ok()) {
+ WireFormatLite::WriteFixed64(field_number, u64.ValueOrDie(), stream);
+ }
+ return u64.status();
+}
+
+// Writes a UINT64 field, including tag, to the stream.
+inline Status WriteUInt64(int field_number, const DataPiece& data,
+ CodedOutputStream* stream) {
+ StatusOr<uint64> u64 = data.ToUint64();
+ if (u64.ok()) {
+ WireFormatLite::WriteUInt64(field_number, u64.ValueOrDie(), stream);
+ }
+ return u64.status();
+}
+
+// Writes a DOUBLE field, including tag, to the stream.
+inline Status WriteDouble(int field_number, const DataPiece& data,
+ CodedOutputStream* stream) {
+ StatusOr<double> d = data.ToDouble();
+ if (d.ok()) {
+ WireFormatLite::WriteDouble(field_number, d.ValueOrDie(), stream);
+ }
+ return d.status();
+}
+
+// Writes a FLOAT field, including tag, to the stream.
+inline Status WriteFloat(int field_number, const DataPiece& data,
+ CodedOutputStream* stream) {
+ StatusOr<float> f = data.ToFloat();
+ if (f.ok()) {
+ WireFormatLite::WriteFloat(field_number, f.ValueOrDie(), stream);
+ }
+ return f.status();
+}
+
+// Writes a BOOL field, including tag, to the stream.
+inline Status WriteBool(int field_number, const DataPiece& data,
+ CodedOutputStream* stream) {
+ StatusOr<bool> b = data.ToBool();
+ if (b.ok()) {
+ WireFormatLite::WriteBool(field_number, b.ValueOrDie(), stream);
+ }
+ return b.status();
+}
+
+// Writes a BYTES field, including tag, to the stream.
+inline Status WriteBytes(int field_number, const DataPiece& data,
+ CodedOutputStream* stream) {
+ StatusOr<string> c = data.ToBytes();
+ if (c.ok()) {
+ WireFormatLite::WriteBytes(field_number, c.ValueOrDie(), stream);
+ }
+ return c.status();
+}
+
+// Writes a STRING field, including tag, to the stream.
+inline Status WriteString(int field_number, const DataPiece& data,
+ CodedOutputStream* stream) {
+ StatusOr<string> s = data.ToString();
+ if (s.ok()) {
+ WireFormatLite::WriteString(field_number, s.ValueOrDie(), stream);
+ }
+ return s.status();
+}
+
+// Writes an ENUM field, including tag, to the stream.
+inline Status WriteEnum(int field_number, const DataPiece& data,
+ const google::protobuf::Enum* enum_type,
+ CodedOutputStream* stream) {
+ StatusOr<int> e = data.ToEnum(enum_type);
+ if (e.ok()) {
+ WireFormatLite::WriteEnum(field_number, e.ValueOrDie(), stream);
+ }
+ return e.status();
+}
+
+// Given a google::protobuf::Type, returns the set of all required fields.
+std::set<const google::protobuf::Field*> GetRequiredFields(
+ const google::protobuf::Type& type) {
+ std::set<const google::protobuf::Field*> required;
+ for (int i = 0; i < type.fields_size(); i++) {
+ const google::protobuf::Field& field = type.fields(i);
+ if (field.cardinality() ==
+ google::protobuf::Field_Cardinality_CARDINALITY_REQUIRED) {
+ required.insert(&field);
+ }
+ }
+ return required;
+}
+
+// Utility method to split a string representation of Timestamp or Duration and
+// return the parts.
+void SplitSecondsAndNanos(StringPiece input, StringPiece* seconds,
+ StringPiece* nanos) {
+ size_t idx = input.rfind('.');
+ if (idx != string::npos) {
+ *seconds = input.substr(0, idx);
+ *nanos = input.substr(idx + 1);
+ } else {
+ *seconds = input;
+ *nanos = StringPiece();
+ }
+}
+
+} // namespace
+
+ProtoStreamObjectWriter::AnyWriter::AnyWriter(ProtoStreamObjectWriter* parent)
+ : parent_(parent),
+ ow_(),
+ invalid_(false),
+ data_(),
+ output_(&data_),
+ depth_(0),
+ has_injected_value_message_(false) {}
+
+ProtoStreamObjectWriter::AnyWriter::~AnyWriter() {}
+
+void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) {
+ ++depth_;
+ // If an object writer is absent, that means we have not called StartAny()
+ // before reaching here. This is an invalid state. StartAny() gets called
+ // whenever we see an "@type" being rendered (see AnyWriter::RenderDataPiece).
+ if (ow_ == NULL) {
+ // Make sure we are not already in an invalid state. This avoids making
+ // multiple unnecessary InvalidValue calls.
+ if (!invalid_) {
+ parent_->InvalidValue("Any",
+ StrCat("Missing or invalid @type for any field in ",
+ parent_->master_type_.name()));
+ invalid_ = true;
+ }
+ } else if (!has_injected_value_message_ || depth_ != 1 || name != "value") {
+ // We don't propagate to ow_ StartObject("value") calls for nested Anys or
+ // Struct at depth 1 as they are nested one level deep with an injected
+ // "value" field.
+ ow_->StartObject(name);
+ }
+}
+
+bool ProtoStreamObjectWriter::AnyWriter::EndObject() {
+ --depth_;
+ // As long as depth_ >= 0, we know we haven't reached the end of Any.
+ // Propagate these EndObject() calls to the contained ow_. If we are in a
+ // nested Any or Struct type, ignore the second to last EndObject call (depth_
+ // == -1)
+ if (ow_ != NULL && (!has_injected_value_message_ || depth_ >= 0)) {
+ ow_->EndObject();
+ }
+ // A negative depth_ implies that we have reached the end of Any
+ // object. Now we write out its contents.
+ if (depth_ < 0) {
+ WriteAny();
+ return false;
+ }
+ return true;
+}
+
+void ProtoStreamObjectWriter::AnyWriter::StartList(StringPiece name) {
+ ++depth_;
+ // We expect ow_ to be present as this call only makes sense inside an Any.
+ if (ow_ == NULL) {
+ if (!invalid_) {
+ parent_->InvalidValue("Any",
+ StrCat("Missing or invalid @type for any field in ",
+ parent_->master_type_.name()));
+ invalid_ = true;
+ }
+ } else {
+ ow_->StartList(name);
+ }
+}
+
+void ProtoStreamObjectWriter::AnyWriter::EndList() {
+ --depth_;
+ if (depth_ < 0) {
+ GOOGLE_LOG(DFATAL) << "Mismatched EndList found, should not be possible";
+ depth_ = 0;
+ }
+ // We don't write an error on the close, only on the open
+ if (ow_ != NULL) {
+ ow_->EndList();
+ }
+}
+
+void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece(
+ StringPiece name, const DataPiece& value) {
+ // Start an Any only at depth_ 0. Other RenderDataPiece calls with "@type"
+ // should go to the contained ow_ as they indicate nested Anys.
+ if (depth_ == 0 && ow_ == NULL && name == "@type") {
+ StartAny(value);
+ } else if (ow_ == NULL) {
+ if (!invalid_) {
+ parent_->InvalidValue("Any",
+ StrCat("Missing or invalid @type for any field in ",
+ parent_->master_type_.name()));
+ invalid_ = true;
+ }
+ } else {
+ // Check to see if the data needs to be rendered with well-known-type
+ // renderer.
+ const TypeRenderer* type_renderer =
+ FindTypeRenderer(GetFullTypeWithUrl(ow_->master_type_.name()));
+ if (type_renderer) {
+ // TODO(rikka): Don't just ignore the util::Status object!
+ (*type_renderer)(ow_.get(), value);
+ } else {
+ ow_->RenderDataPiece(name, value);
+ }
+ }
+}
+
+void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) {
+ // Figure out the type url. This is a copy-paste from WriteString but we also
+ // need the value, so we can't just call through to that.
+ if (value.type() == DataPiece::TYPE_STRING) {
+ type_url_ = value.str().ToString();
+ } else {
+ StatusOr<string> s = value.ToString();
+ if (!s.ok()) {
+ parent_->InvalidValue("String", s.status().error_message());
+ invalid_ = true;
+ return;
+ }
+ type_url_ = s.ValueOrDie();
+ }
+ // Resolve the type url, and report an error if we failed to resolve it.
+ StatusOr<const google::protobuf::Type*> resolved_type =
+ parent_->typeinfo_->ResolveTypeUrl(type_url_);
+ if (!resolved_type.ok()) {
+ parent_->InvalidValue("Any", resolved_type.status().error_message());
+ invalid_ = true;
+ return;
+ }
+ // At this point, type is never null.
+ const google::protobuf::Type* type = resolved_type.ValueOrDie();
+
+ // If this is the case of an Any in an Any or Struct in an Any, we need to
+ // expect a StartObject call with "value" while we're at depth_ 0, which we
+ // should ignore (not propagate to our nested object writer). We also need to
+ // ignore the second-to-last EndObject call, and not propagate that either.
+ if (type->name() == kAnyType || type->name() == kStructType) {
+ has_injected_value_message_ = true;
+ }
+
+ // Create our object writer and initialize it with the first StartObject
+ // call.
+ ow_.reset(new ProtoStreamObjectWriter(parent_->typeinfo_, *type, &output_,
+ parent_->listener_));
+ ow_->StartObject("");
+}
+
+void ProtoStreamObjectWriter::AnyWriter::WriteAny() {
+ if (ow_ == NULL) {
+ // If we had no object writer, we never got any content, so just return
+ // immediately, which is equivalent to writing an empty Any.
+ return;
+ }
+ // Render the type_url and value fields directly to the stream.
+ // type_url has tag 1 and value has tag 2.
+ WireFormatLite::WriteString(1, type_url_, parent_->stream_.get());
+ if (!data_.empty()) {
+ WireFormatLite::WriteBytes(2, data_, parent_->stream_.get());
+ }
+}
+
+ProtoStreamObjectWriter::ProtoElement::ProtoElement(
+ TypeInfo* typeinfo, const google::protobuf::Type& type,
+ ProtoStreamObjectWriter* enclosing)
+ : BaseElement(NULL),
+ ow_(enclosing),
+ any_(),
+ field_(NULL),
+ typeinfo_(typeinfo),
+ type_(type),
+ required_fields_(GetRequiredFields(type)),
+ is_repeated_type_(false),
+ size_index_(-1),
+ array_index_(-1),
+ element_type_(GetElementType(type_)) {
+ if (element_type_ == ANY) {
+ any_.reset(new AnyWriter(ow_));
+ }
+}
+
+ProtoStreamObjectWriter::ProtoElement::ProtoElement(
+ ProtoStreamObjectWriter::ProtoElement* parent,
+ const google::protobuf::Field* field, const google::protobuf::Type& type,
+ ElementType element_type)
+ : BaseElement(parent),
+ ow_(this->parent()->ow_),
+ any_(),
+ field_(field),
+ typeinfo_(this->parent()->typeinfo_),
+ type_(type),
+ is_repeated_type_(element_type == ProtoElement::LIST ||
+ element_type == ProtoElement::STRUCT_LIST ||
+ element_type == ProtoElement::MAP ||
+ element_type == ProtoElement::STRUCT_MAP),
+ size_index_(!is_repeated_type_ &&
+ field->kind() ==
+ google::protobuf::Field_Kind_TYPE_MESSAGE
+ ? ow_->size_insert_.size()
+ : -1),
+ array_index_(is_repeated_type_ ? 0 : -1),
+ element_type_(element_type) {
+ if (!is_repeated_type_) {
+ if (field->cardinality() ==
+ google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) {
+ // Update array_index_ if it is an explicit list.
+ if (this->parent()->array_index_ >= 0) this->parent()->array_index_++;
+ } else {
+ this->parent()->RegisterField(field);
+ }
+ if (field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) {
+ required_fields_ = GetRequiredFields(type_);
+ int start_pos = ow_->stream_->ByteCount();
+ // length of serialized message is the final buffer position minus
+ // starting buffer position, plus length adjustments for size fields
+ // of any nested messages. We start with -start_pos here, so we only
+ // need to add the final buffer position to it at the end.
+ SizeInfo info = {start_pos, -start_pos};
+ ow_->size_insert_.push_back(info);
+ }
+ }
+ if (element_type == ANY) {
+ any_.reset(new AnyWriter(ow_));
+ }
+}
+
+ProtoStreamObjectWriter::ProtoElement*
+ProtoStreamObjectWriter::ProtoElement::pop() {
+ // Calls the registered error listener for any required field(s) not yet
+ // seen.
+ for (set<const google::protobuf::Field*>::iterator it =
+ required_fields_.begin();
+ it != required_fields_.end(); ++it) {
+ ow_->MissingField((*it)->name());
+ }
+ // Computes the total number of proto bytes used by a message, also adjusts
+ // the size of all parent messages by the length of this size field.
+ // If size_index_ < 0, this is not a message, so no size field is added.
+ if (size_index_ >= 0) {
+ // Add the final buffer position to compute the total length of this
+ // serialized message. The stored value (before this addition) already
+ // contains the total length of the size fields of all nested messages
+ // minus the initial buffer position.
+ ow_->size_insert_[size_index_].size += ow_->stream_->ByteCount();
+ // Calculate the length required to serialize the size field of the
+ // message, and propagate this additional size information upward to
+ // all enclosing messages.
+ int size = ow_->size_insert_[size_index_].size;
+ int length = CodedOutputStream::VarintSize32(size);
+ for (ProtoElement* e = parent(); e != NULL; e = e->parent()) {
+ // Only nested messages have size field, lists do not have size field.
+ if (e->size_index_ >= 0) {
+ ow_->size_insert_[e->size_index_].size += length;
+ }
+ }
+ }
+ return BaseElement::pop<ProtoElement>();
+}
+
+void ProtoStreamObjectWriter::ProtoElement::RegisterField(
+ const google::protobuf::Field* field) {
+ if (!required_fields_.empty() &&
+ field->cardinality() ==
+ google::protobuf::Field_Cardinality_CARDINALITY_REQUIRED) {
+ required_fields_.erase(field);
+ }
+}
+
+string ProtoStreamObjectWriter::ProtoElement::ToString() const {
+ if (parent() == NULL) return "";
+ string loc = parent()->ToString();
+ if (field_->cardinality() !=
+ google::protobuf::Field_Cardinality_CARDINALITY_REPEATED ||
+ parent()->field_ != field_) {
+ string name = field_->name();
+ int i = 0;
+ while (i < name.size() && (ascii_isalnum(name[i]) || name[i] == '_')) ++i;
+ if (i > 0 && i == name.size()) { // safe field name
+ if (loc.empty()) {
+ loc = name;
+ } else {
+ StrAppend(&loc, ".", name);
+ }
+ } else {
+ StrAppend(&loc, "[\"", CEscape(name), "\"]");
+ }
+ }
+ if (field_->cardinality() ==
+ google::protobuf::Field_Cardinality_CARDINALITY_REPEATED &&
+ array_index_ > 0) {
+ StrAppend(&loc, "[", array_index_ - 1, "]");
+ }
+ return loc.empty() ? "." : loc;
+}
+
+inline void ProtoStreamObjectWriter::InvalidName(StringPiece unknown_name,
+ StringPiece message) {
+ listener_->InvalidName(location(), ToSnakeCase(unknown_name), message);
+}
+
+inline void ProtoStreamObjectWriter::InvalidValue(StringPiece type_name,
+ StringPiece value) {
+ listener_->InvalidValue(location(), type_name, value);
+}
+
+inline void ProtoStreamObjectWriter::MissingField(StringPiece missing_name) {
+ listener_->MissingField(location(), missing_name);
+}
+
+ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject(
+ StringPiece name) {
+ // Starting the root message. Create the root ProtoElement and return.
+ if (element_ == NULL) {
+ if (!name.empty()) {
+ InvalidName(name, "Root element should not be named.");
+ }
+ element_.reset(new ProtoElement(typeinfo_, master_type_, this));
+
+ // If master type is a special type that needs extra values to be written to
+ // stream, we write those values.
+ if (master_type_.name() == kStructType) {
+ StartStruct(NULL);
+ } else if (master_type_.name() == kStructValueType) {
+ // We got a StartObject call with google.protobuf.Value field. This means
+ // we are starting an object within google.protobuf.Value type. The only
+ // object within that type is a struct type. So start a struct.
+ const google::protobuf::Field* field = StartStructValueInStruct(NULL);
+ StartStruct(field);
+ }
+ return this;
+ }
+
+ const google::protobuf::Field* field = NULL;
+ if (element_ != NULL && element_->IsAny()) {
+ element_->any()->StartObject(name);
+ return this;
+ } else if (element_ != NULL &&
+ (element_->IsMap() || element_->IsStructMap())) {
+ field = StartMapEntry(name);
+ if (element_->IsStructMapEntry()) {
+ // If the top element is a map entry, this means we are starting another
+ // struct within a struct.
+ field = StartStructValueInStruct(field);
+ }
+ } else if (element_ != NULL && element_->IsStructList()) {
+ // If the top element is a list, then we are starting a list field within a
+ // struct.
+ field = Lookup(name);
+ field = StartStructValueInStruct(field);
+ } else {
+ field = BeginNamed(name, false);
+ }
+ if (field == NULL) {
+ return this;
+ }
+
+ const google::protobuf::Type* type = LookupType(field);
+ if (type == NULL) {
+ ++invalid_depth_;
+ InvalidName(name,
+ StrCat("Missing descriptor for field: ", field->type_url()));
+ return this;
+ }
+
+ if (field->type_url() == GetFullTypeWithUrl(kStructType)) {
+ // Start a struct object.
+ StartStruct(field);
+ } else if (field->type_url() == GetFullTypeWithUrl(kStructValueType)) {
+ // We got a StartObject call with google.protobuf.Value field. This means we
+ // are starting an object within google.protobuf.Value type. The only object
+ // within that type is a struct type. So start a struct.
+ field = StartStructValueInStruct(field);
+ StartStruct(field);
+ } else if (field->type_url() == GetFullTypeWithUrl(kAnyType)) {
+ // Begin an Any. We can't do the real work till we get the @type field.
+ WriteTag(*field);
+ element_.reset(
+ new ProtoElement(element_.release(), field, *type, ProtoElement::ANY));
+ } else if (IsMap(*field)) {
+ // Begin a map.
+ // A map is triggered by a StartObject() call if the current field has a map
+ // type. Map values are written to proto in a manner detailed in comments
+ // above StartMapEntry() function.
+ element_.reset(
+ new ProtoElement(element_.release(), field, *type, ProtoElement::MAP));
+ } else {
+ WriteTag(*field);
+ element_.reset(new ProtoElement(element_.release(), field, *type,
+ ProtoElement::MESSAGE));
+ }
+ return this;
+}
+
+// Proto3 maps are represented on the wire as a message with
+// "key" and a "value".
+//
+// For example, the syntax:
+// map<key_type, value_type> map_field = N;
+//
+// is represented as:
+// message MapFieldEntry {
+// option map_entry = true; // marks the map construct in the descriptor
+//
+// key_type key = 1;
+// value_type value = 2;
+// }
+// repeated MapFieldEntry map_field = N;
+//
+// See go/proto3-maps for more information.
+const google::protobuf::Field* ProtoStreamObjectWriter::StartMapEntry(
+ StringPiece name) {
+ // top of stack is already a map field
+ const google::protobuf::Field* field = element_->field();
+ const google::protobuf::Type& type = element_->type();
+ // If we come from a regular map, use MAP_ENTRY or if we come from a struct,
+ // use STRUCT_MAP_ENTRY. These values are used later in StartObject/StartList
+ // or RenderDataPiece for making appropriate decisions.
+ ProtoElement::ElementType element_type = element_->IsStructMap()
+ ? ProtoElement::STRUCT_MAP_ENTRY
+ : ProtoElement::MAP_ENTRY;
+ WriteTag(*field);
+ element_.reset(
+ new ProtoElement(element_.release(), field, type, element_type));
+ RenderDataPiece("key", DataPiece(name));
+ return BeginNamed("value", false);
+}
+
+// Starts a google.protobuf.Struct.
+// 'field' represents a field in a message of type google.protobuf.Struct. A
+// struct contains a map with name 'fields'. This function starts this map as
+// well.
+// When 'field' is NULL, it means that the top level message is of struct
+// type.
+void ProtoStreamObjectWriter::StartStruct(
+ const google::protobuf::Field* field) {
+ const google::protobuf::Type* type = NULL;
+ if (field) {
+ type = LookupType(field);
+ WriteTag(*field);
+ element_.reset(new ProtoElement(element_.release(), field, *type,
+ ProtoElement::STRUCT));
+ }
+ const google::protobuf::Field* struct_field = BeginNamed("fields", false);
+
+ if (!struct_field) {
+ // It is a programmatic error if this happens. Log an error.
+ GOOGLE_LOG(ERROR) << "Invalid internal state. Cannot find 'fields' within "
+ << (field ? field->type_url() : "google.protobuf.Struct");
+ return;
+ }
+
+ type = LookupType(struct_field);
+ element_.reset(new ProtoElement(element_.release(), struct_field, *type,
+ ProtoElement::STRUCT_MAP));
+}
+
+// Starts a "struct_value" within struct.proto's google.protobuf.Value type.
+// 'field' should be of the type google.protobuf.Value.
+// Returns the field identifying "struct_value" within the given field.
+//
+// If field is NULL, then we are starting struct_value at the top-level, in
+// this case skip writing any tag information for the passed field.
+const google::protobuf::Field*
+ProtoStreamObjectWriter::StartStructValueInStruct(
+ const google::protobuf::Field* field) {
+ if (field) {
+ const google::protobuf::Type* type = LookupType(field);
+ WriteTag(*field);
+ element_.reset(new ProtoElement(element_.release(), field, *type,
+ ProtoElement::STRUCT_VALUE));
+ }
+ return BeginNamed("struct_value", false);
+}
+
+// Starts a "list_value" within struct.proto's google.protobuf.Value type.
+// 'field' should be of the type google.protobuf.Value.
+// Returns the field identifying "list_value" within the given field.
+//
+// If field is NULL, then we are starting list_value at the top-level, in
+// this case skip writing any tag information for the passed field.
+const google::protobuf::Field* ProtoStreamObjectWriter::StartListValueInStruct(
+ const google::protobuf::Field* field) {
+ if (field) {
+ const google::protobuf::Type* type = LookupType(field);
+ WriteTag(*field);
+ element_.reset(new ProtoElement(element_.release(), field, *type,
+ ProtoElement::STRUCT_VALUE));
+ }
+ const google::protobuf::Field* list_value = BeginNamed("list_value", false);
+
+ if (!list_value) {
+ // It is a programmatic error if this happens. Log an error.
+ GOOGLE_LOG(ERROR) << "Invalid internal state. Cannot find 'list_value' within "
+ << (field ? field->type_url() : "google.protobuf.Value");
+ return field;
+ }
+
+ return StartRepeatedValuesInListValue(list_value);
+}
+
+// Starts the repeated "values" field in struct.proto's
+// google.protobuf.ListValue type. 'field' should be of type
+// google.protobuf.ListValue.
+//
+// If field is NULL, then we are starting ListValue at the top-level, in
+// this case skip writing any tag information for the passed field.
+const google::protobuf::Field*
+ProtoStreamObjectWriter::StartRepeatedValuesInListValue(
+ const google::protobuf::Field* field) {
+ if (field) {
+ const google::protobuf::Type* type = LookupType(field);
+ WriteTag(*field);
+ element_.reset(new ProtoElement(element_.release(), field, *type,
+ ProtoElement::STRUCT_LIST_VALUE));
+ }
+ return BeginNamed("values", true);
+}
+
+void ProtoStreamObjectWriter::SkipElements() {
+ if (element_ == NULL) return;
+
+ ProtoElement::ElementType element_type = element_->element_type();
+ while (element_type == ProtoElement::STRUCT ||
+ element_type == ProtoElement::STRUCT_LIST_VALUE ||
+ element_type == ProtoElement::STRUCT_VALUE ||
+ element_type == ProtoElement::STRUCT_MAP_ENTRY ||
+ element_type == ProtoElement::MAP_ENTRY) {
+ element_.reset(element_->pop());
+ element_type =
+ element_ != NULL ? element_->element_type() : ProtoElement::MESSAGE;
+ }
+}
+
+ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndObject() {
+ if (invalid_depth_ > 0) {
+ --invalid_depth_;
+ return this;
+ }
+ if (element_ != NULL && element_->IsAny()) {
+ if (element_->any()->EndObject()) {
+ return this;
+ }
+ }
+ if (element_ != NULL) {
+ element_.reset(element_->pop());
+ }
+
+ // Skip sentinel elements added to keep track of new proto3 types - map,
+ // struct.
+ SkipElements();
+
+ // If ending the root element,
+ // then serialize the full message with calculated sizes.
+ if (element_ == NULL) {
+ WriteRootMessage();
+ }
+ return this;
+}
+
+ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) {
+ const google::protobuf::Field* field = NULL;
+ // Since we cannot have a top-level repeated item in protobuf, the only way
+ // element_ can be null when here is when we start a top-level list
+ // google.protobuf.ListValue.
+ if (element_ == NULL) {
+ if (!name.empty()) {
+ InvalidName(name, "Root element should not be named.");
+ }
+ element_.reset(new ProtoElement(typeinfo_, master_type_, this));
+
+ // If master type is a special type that needs extra values to be written to
+ // stream, we write those values.
+ if (master_type_.name() == kStructValueType) {
+ // We got a StartList with google.protobuf.Value master type. This means
+ // we have to start the "list_value" within google.protobuf.Value.
+ field = StartListValueInStruct(NULL);
+ } else if (master_type_.name() == kStructListValueType) {
+ // We got a StartList with google.protobuf.ListValue master type. This
+ // means we have to start the "values" within google.protobuf.ListValue.
+ field = StartRepeatedValuesInListValue(NULL);
+ }
+
+ // field is NULL when master_type_ is anything other than
+ // google.protobuf.Value or google.protobuf.ListValue.
+ if (field) {
+ const google::protobuf::Type* type = LookupType(field);
+ element_.reset(new ProtoElement(element_.release(), field, *type,
+ ProtoElement::STRUCT_LIST));
+ }
+ return this;
+ }
+
+ if (element_->IsAny()) {
+ element_->any()->StartList(name);
+ return this;
+ }
+ // The type of element we push to stack.
+ ProtoElement::ElementType element_type = ProtoElement::LIST;
+
+ // Check if we need to start a map. This can heppen when there is either a map
+ // or a struct type within a list.
+ if (element_->IsMap() || element_->IsStructMap()) {
+ field = StartMapEntry(name);
+ if (field == NULL) return this;
+
+ if (element_->IsStructMapEntry()) {
+ // If the top element is a map entry, this means we are starting a list
+ // within a struct or a map.
+ // An example sequence of calls would be
+ // StartObject -> StartList
+ field = StartListValueInStruct(field);
+ if (field == NULL) return this;
+ }
+
+ element_type = ProtoElement::STRUCT_LIST;
+ } else if (element_->IsStructList()) {
+ // If the top element is a STRUCT_LIST, this means we are starting a list
+ // within the current list (inside a struct).
+ // An example call sequence would be
+ // StartObject -> StartList -> StartList
+ // with StartObject starting a struct.
+
+ // Lookup the last list type in element stack as we are adding an element of
+ // the same type.
+ field = Lookup(name);
+ if (field == NULL) return this;
+
+ field = StartListValueInStruct(field);
+ if (field == NULL) return this;
+
+ element_type = ProtoElement::STRUCT_LIST;
+ } else {
+ // Lookup field corresponding to 'name'. If it is a google.protobuf.Value
+ // or google.protobuf.ListValue type, then StartList is a valid call, start
+ // this list.
+ // We cannot use Lookup() here as it will produce InvalidName() error if the
+ // field is not found. We do not want to error here as it would cause us to
+ // report errors twice, once here and again later in BeginNamed() call.
+ // Also we ignore if the field is not found here as it is caught later.
+ field = typeinfo_->FindField(&element_->type(), name);
+
+ // It is an error to try to bind to map, which behind the scenes is a list.
+ if (field && IsMap(*field)) {
+ // Push field to stack for error location tracking & reporting.
+ element_.reset(new ProtoElement(element_.release(), field,
+ *LookupType(field),
+ ProtoElement::MESSAGE));
+ InvalidValue("Map", "Cannot bind a list to map.");
+ ++invalid_depth_;
+ element_->pop();
+ return this;
+ }
+
+ if (field && field->type_url() == GetFullTypeWithUrl(kStructValueType)) {
+ // There are 2 cases possible:
+ // a. g.p.Value is repeated
+ // b. g.p.Value is not repeated
+ //
+ // For case (a), the StartList should bind to the repeated g.p.Value.
+ // For case (b), the StartList should bind to g.p.ListValue within the
+ // g.p.Value.
+ //
+ // This means, for case (a), we treat it just like any other repeated
+ // message, except we would apply an appropriate element_type so future
+ // Start or Render calls are routed appropriately.
+ if (field->cardinality() !=
+ google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) {
+ field = StartListValueInStruct(field);
+ }
+ element_type = ProtoElement::STRUCT_LIST;
+ } else if (field &&
+ field->type_url() == GetFullTypeWithUrl(kStructListValueType)) {
+ // We got a StartList with google.protobuf.ListValue master type. This
+ // means we have to start the "values" within google.protobuf.ListValue.
+ field = StartRepeatedValuesInListValue(field);
+ } else {
+ // If no special types are to be bound, fall back to normal processing of
+ // StartList.
+ field = BeginNamed(name, true);
+ }
+ if (field == NULL) return this;
+ }
+
+ const google::protobuf::Type* type = LookupType(field);
+ if (type == NULL) {
+ ++invalid_depth_;
+ InvalidName(name,
+ StrCat("Missing descriptor for field: ", field->type_url()));
+ return this;
+ }
+
+ element_.reset(
+ new ProtoElement(element_.release(), field, *type, element_type));
+ return this;
+}
+
+ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndList() {
+ if (invalid_depth_ > 0) {
+ --invalid_depth_;
+ } else if (element_ != NULL) {
+ if (element_->IsAny()) {
+ element_->any()->EndList();
+ } else {
+ element_.reset(element_->pop());
+ // Skip sentinel elements added to keep track of new proto3 types - map,
+ // struct.
+ SkipElements();
+ }
+ }
+
+ // When element_ is NULL, we have reached the root message type. Write out
+ // the bytes.
+ if (element_ == NULL) {
+ WriteRootMessage();
+ }
+ return this;
+}
+
+Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow,
+ const DataPiece& data) {
+ string struct_field_name;
+ switch (data.type()) {
+ // Our JSON parser parses numbers as either int64, uint64, or double.
+ case DataPiece::TYPE_INT64:
+ case DataPiece::TYPE_UINT64:
+ case DataPiece::TYPE_DOUBLE: {
+ struct_field_name = "number_value";
+ break;
+ }
+ case DataPiece::TYPE_STRING: {
+ struct_field_name = "string_value";
+ break;
+ }
+ case DataPiece::TYPE_BOOL: {
+ struct_field_name = "bool_value";
+ break;
+ }
+ case DataPiece::TYPE_NULL: {
+ struct_field_name = "null_value";
+ break;
+ }
+ default: {
+ return Status(INVALID_ARGUMENT,
+ "Invalid struct data type. Only number, string, boolean or "
+ "null values are supported.");
+ }
+ }
+ ow->RenderDataPiece(struct_field_name, data);
+ return Status::OK;
+}
+
+Status ProtoStreamObjectWriter::RenderTimestamp(ProtoStreamObjectWriter* ow,
+ const DataPiece& data) {
+ if (data.type() != DataPiece::TYPE_STRING) {
+ return Status(INVALID_ARGUMENT,
+ StrCat("Invalid data type for timestamp, value is ",
+ data.ValueAsStringOrDefault("")));
+ }
+
+ StringPiece value(data.str());
+
+ int64 seconds;
+ int32 nanos;
+ if (!::google::protobuf::internal::ParseTime(value.ToString(), &seconds,
+ &nanos)) {
+ return Status(INVALID_ARGUMENT, StrCat("Invalid time format: ", value));
+ }
+
+
+ ow->RenderDataPiece("seconds", DataPiece(seconds));
+ ow->RenderDataPiece("nanos", DataPiece(nanos));
+ return Status::OK;
+}
+
+static inline util::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow,
+ StringPiece path) {
+ ow->RenderDataPiece("paths",
+ DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase)));
+ return Status::OK;
+}
+
+Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow,
+ const DataPiece& data) {
+ if (data.type() != DataPiece::TYPE_STRING) {
+ return Status(INVALID_ARGUMENT,
+ StrCat("Invalid data type for field mask, value is ",
+ data.ValueAsStringOrDefault("")));
+ }
+
+ // TODO(tsun): figure out how to do proto descriptor based snake case
+ // conversions as much as possible. Because ToSnakeCase sometimes returns the
+ // wrong value.
+ google::protobuf::scoped_ptr<ResultCallback1<util::Status, StringPiece> > callback(
+ NewPermanentCallback(&RenderOneFieldPath, ow));
+ return DecodeCompactFieldMaskPaths(data.str(), callback.get());
+}
+
+Status ProtoStreamObjectWriter::RenderDuration(ProtoStreamObjectWriter* ow,
+ const DataPiece& data) {
+ if (data.type() != DataPiece::TYPE_STRING) {
+ return Status(INVALID_ARGUMENT,
+ StrCat("Invalid data type for duration, value is ",
+ data.ValueAsStringOrDefault("")));
+ }
+
+ StringPiece value(data.str());
+
+ if (!value.ends_with("s")) {
+ return Status(INVALID_ARGUMENT,
+ "Illegal duration format; duration must end with 's'");
+ }
+ value = value.substr(0, value.size() - 1);
+ int sign = 1;
+ if (value.starts_with("-")) {
+ sign = -1;
+ value = value.substr(1);
+ }
+
+ StringPiece s_secs, s_nanos;
+ SplitSecondsAndNanos(value, &s_secs, &s_nanos);
+ uint64 unsigned_seconds;
+ if (!safe_strtou64(s_secs, &unsigned_seconds)) {
+ return Status(INVALID_ARGUMENT,
+ "Invalid duration format, failed to parse seconds");
+ }
+
+ double d_nanos = 0;
+ if (!safe_strtod("0." + s_nanos.ToString(), &d_nanos)) {
+ return Status(INVALID_ARGUMENT,
+ "Invalid duration format, failed to parse nanos seconds");
+ }
+
+ int32 nanos = sign * static_cast<int32>(d_nanos * kNanosPerSecond);
+ int64 seconds = sign * unsigned_seconds;
+
+ if (seconds > kMaxSeconds || seconds < kMinSeconds ||
+ nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
+ return Status(INVALID_ARGUMENT, "Duration value exceeds limits");
+ }
+
+ ow->RenderDataPiece("seconds", DataPiece(seconds));
+ ow->RenderDataPiece("nanos", DataPiece(nanos));
+ return Status::OK;
+}
+
+Status ProtoStreamObjectWriter::RenderWrapperType(ProtoStreamObjectWriter* ow,
+ const DataPiece& data) {
+ ow->RenderDataPiece("value", data);
+ return Status::OK;
+}
+
+ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece(
+ StringPiece name, const DataPiece& data) {
+ Status status;
+ if (invalid_depth_ > 0) return this;
+ if (element_ != NULL && element_->IsAny()) {
+ element_->any()->RenderDataPiece(name, data);
+ return this;
+ }
+
+ const google::protobuf::Field* field = NULL;
+ string type_url;
+ bool is_map_entry = false;
+ if (element_ == NULL) {
+ type_url = GetFullTypeWithUrl(master_type_.name());
+ } else {
+ if (element_->IsMap() || element_->IsStructMap()) {
+ is_map_entry = true;
+ field = StartMapEntry(name);
+ } else {
+ field = Lookup(name);
+ }
+ if (field == NULL) {
+ return this;
+ }
+ type_url = field->type_url();
+ }
+
+ // Check if there are any well known type renderers available for type_url.
+ const TypeRenderer* type_renderer = FindTypeRenderer(type_url);
+ if (type_renderer != NULL) {
+ // Push the current element to stack so lookups in type_renderer will
+ // find the fields. We do an EndObject soon after, which pops this. This is
+ // safe because all well-known types are messages.
+ if (element_ == NULL) {
+ element_.reset(new ProtoElement(typeinfo_, master_type_, this));
+ } else {
+ if (field) {
+ WriteTag(*field);
+ const google::protobuf::Type* type = LookupType(field);
+ element_.reset(new ProtoElement(element_.release(), field, *type,
+ ProtoElement::MESSAGE));
+ }
+ }
+ status = (*type_renderer)(this, data);
+ if (!status.ok()) {
+ InvalidValue(type_url,
+ StrCat("Field '", name, "', ", status.error_message()));
+ }
+ EndObject();
+ return this;
+ } else if (element_ == NULL) { // no message type found at root
+ element_.reset(new ProtoElement(typeinfo_, master_type_, this));
+ InvalidName(name, "Root element must be a message.");
+ return this;
+ }
+
+ if (field == NULL) {
+ return this;
+ }
+ const google::protobuf::Type* type = LookupType(field);
+ if (type == NULL) {
+ InvalidName(name,
+ StrCat("Missing descriptor for field: ", field->type_url()));
+ return this;
+ }
+
+ // Whether we should pop at the end. Set to true if the data field is a
+ // message type, which can happen in case of struct values.
+ bool should_pop = false;
+
+ RenderSimpleDataPiece(*field, *type, data);
+
+ if (should_pop && element_ != NULL) {
+ element_.reset(element_->pop());
+ }
+
+ if (is_map_entry) {
+ // Ending map is the same as ending an object.
+ EndObject();
+ }
+ return this;
+}
+
+void ProtoStreamObjectWriter::RenderSimpleDataPiece(
+ const google::protobuf::Field& field, const google::protobuf::Type& type,
+ const DataPiece& data) {
+ // If we are rendering explicit null values and the backend proto field is not
+ // of the google.protobuf.NullType type, we do nothing.
+ if (data.type() == DataPiece::TYPE_NULL &&
+ field.type_url() != kStructNullValueTypeUrl) {
+ return;
+ }
+
+ // Pushing a ProtoElement and then pop it off at the end for 2 purposes:
+ // error location reporting and required field accounting.
+ element_.reset(new ProtoElement(element_.release(), &field, type,
+ ProtoElement::MESSAGE));
+
+ // Make sure that field represents a simple data type.
+ if (field.kind() == google::protobuf::Field_Kind_TYPE_UNKNOWN ||
+ field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) {
+ InvalidValue(field.type_url().empty()
+ ? google::protobuf::Field_Kind_Name(field.kind())
+ : field.type_url(),
+ data.ValueAsStringOrDefault(""));
+ return;
+ }
+
+ Status status;
+ switch (field.kind()) {
+ case google::protobuf::Field_Kind_TYPE_INT32: {
+ status = WriteInt32(field.number(), data, stream_.get());
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_SFIXED32: {
+ status = WriteSFixed32(field.number(), data, stream_.get());
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_SINT32: {
+ status = WriteSInt32(field.number(), data, stream_.get());
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_FIXED32: {
+ status = WriteFixed32(field.number(), data, stream_.get());
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_UINT32: {
+ status = WriteUInt32(field.number(), data, stream_.get());
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_INT64: {
+ status = WriteInt64(field.number(), data, stream_.get());
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_SFIXED64: {
+ status = WriteSFixed64(field.number(), data, stream_.get());
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_SINT64: {
+ status = WriteSInt64(field.number(), data, stream_.get());
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_FIXED64: {
+ status = WriteFixed64(field.number(), data, stream_.get());
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_UINT64: {
+ status = WriteUInt64(field.number(), data, stream_.get());
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_DOUBLE: {
+ status = WriteDouble(field.number(), data, stream_.get());
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_FLOAT: {
+ status = WriteFloat(field.number(), data, stream_.get());
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_BOOL: {
+ status = WriteBool(field.number(), data, stream_.get());
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_BYTES: {
+ status = WriteBytes(field.number(), data, stream_.get());
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_STRING: {
+ status = WriteString(field.number(), data, stream_.get());
+ break;
+ }
+ case google::protobuf::Field_Kind_TYPE_ENUM: {
+ status = WriteEnum(field.number(), data,
+ typeinfo_->GetEnum(field.type_url()), stream_.get());
+ break;
+ }
+ default: // TYPE_GROUP or TYPE_MESSAGE
+ status = Status(INVALID_ARGUMENT, data.ToString().ValueOrDie());
+ }
+ if (!status.ok()) {
+ InvalidValue(google::protobuf::Field_Kind_Name(field.kind()),
+ status.error_message());
+ }
+ element_.reset(element_->pop());
+}
+
+// Map of functions that are responsible for rendering well known type
+// represented by the key.
+hash_map<string, ProtoStreamObjectWriter::TypeRenderer>*
+ProtoStreamObjectWriter::CreateRendererMap() {
+ google::protobuf::scoped_ptr<hash_map<string, ProtoStreamObjectWriter::TypeRenderer> >
+ result(new hash_map<string, ProtoStreamObjectWriter::TypeRenderer>());
+ (*result)["type.googleapis.com/google.protobuf.Timestamp"] =
+ &ProtoStreamObjectWriter::RenderTimestamp;
+ (*result)["type.googleapis.com/google.protobuf.Duration"] =
+ &ProtoStreamObjectWriter::RenderDuration;
+ (*result)["type.googleapis.com/google.protobuf.FieldMask"] =
+ &ProtoStreamObjectWriter::RenderFieldMask;
+ (*result)["type.googleapis.com/google.protobuf.Double"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.Float"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.Int64"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.UInt64"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.Int32"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.UInt32"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.Bool"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.String"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.Bytes"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.DoubleValue"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.FloatValue"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.Int64Value"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.UInt64Value"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.Int32Value"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.UInt32Value"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.BoolValue"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.StringValue"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.BytesValue"] =
+ &ProtoStreamObjectWriter::RenderWrapperType;
+ (*result)["type.googleapis.com/google.protobuf.Value"] =
+ &ProtoStreamObjectWriter::RenderStructValue;
+ return result.release();
+}
+
+ProtoStreamObjectWriter::TypeRenderer*
+ProtoStreamObjectWriter::FindTypeRenderer(const string& type_url) {
+ static hash_map<string, TypeRenderer>* renderers = CreateRendererMap();
+ return FindOrNull(*renderers, type_url);
+}
+
+ProtoStreamObjectWriter::ProtoElement::ElementType
+ProtoStreamObjectWriter::GetElementType(const google::protobuf::Type& type) {
+ if (type.name() == kAnyType) {
+ return ProtoElement::ANY;
+ } else if (type.name() == kStructType) {
+ return ProtoElement::STRUCT;
+ } else if (type.name() == kStructValueType) {
+ return ProtoElement::STRUCT_VALUE;
+ } else if (type.name() == kStructListValueType) {
+ return ProtoElement::STRUCT_LIST_VALUE;
+ } else {
+ return ProtoElement::MESSAGE;
+ }
+}
+
+const google::protobuf::Field* ProtoStreamObjectWriter::BeginNamed(
+ StringPiece name, bool is_list) {
+ if (invalid_depth_ > 0) {
+ ++invalid_depth_;
+ return NULL;
+ }
+ const google::protobuf::Field* field = Lookup(name);
+ if (field == NULL) {
+ ++invalid_depth_;
+ // InvalidName() already called in Lookup().
+ return NULL;
+ }
+ if (is_list &&
+ field->cardinality() !=
+ google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) {
+ ++invalid_depth_;
+ InvalidName(name, "Proto field is not repeating, cannot start list.");
+ return NULL;
+ }
+ return field;
+}
+
+const google::protobuf::Field* ProtoStreamObjectWriter::Lookup(
+ StringPiece unnormalized_name) {
+ ProtoElement* e = element();
+ if (e == NULL) {
+ InvalidName(unnormalized_name, "Root element must be a message.");
+ return NULL;
+ }
+ if (unnormalized_name.empty()) {
+ // Objects in repeated field inherit the same field descriptor.
+ if (e->field() == NULL) {
+ InvalidName(unnormalized_name, "Proto fields must have a name.");
+ } else if (e->field()->cardinality() !=
+ google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) {
+ InvalidName(unnormalized_name, "Proto fields must have a name.");
+ return NULL;
+ }
+ return e->field();
+ }
+ const google::protobuf::Field* field =
+ typeinfo_->FindField(&e->type(), unnormalized_name);
+ if (field == NULL) InvalidName(unnormalized_name, "Cannot find field.");
+ return field;
+}
+
+const google::protobuf::Type* ProtoStreamObjectWriter::LookupType(
+ const google::protobuf::Field* field) {
+ return (field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE
+ ? typeinfo_->GetType(field->type_url())
+ : &element_->type());
+}
+
+// Looks up the oneof struct field based on the data type.
+StatusOr<const google::protobuf::Field*>
+ProtoStreamObjectWriter::LookupStructField(DataPiece::Type type) {
+ const google::protobuf::Field* field = NULL;
+ switch (type) {
+ // Our JSON parser parses numbers as either int64, uint64, or double.
+ case DataPiece::TYPE_INT64:
+ case DataPiece::TYPE_UINT64:
+ case DataPiece::TYPE_DOUBLE: {
+ field = Lookup("number_value");
+ break;
+ }
+ case DataPiece::TYPE_STRING: {
+ field = Lookup("string_value");
+ break;
+ }
+ case DataPiece::TYPE_BOOL: {
+ field = Lookup("bool_value");
+ break;
+ }
+ case DataPiece::TYPE_NULL: {
+ field = Lookup("null_value");
+ break;
+ }
+ default: { return Status(INVALID_ARGUMENT, "Invalid struct data type"); }
+ }
+ if (field == NULL) {
+ return Status(INVALID_ARGUMENT, "Could not lookup struct field");
+ }
+ return field;
+}
+
+void ProtoStreamObjectWriter::WriteRootMessage() {
+ GOOGLE_DCHECK(!done_);
+ int curr_pos = 0;
+ // Calls the destructor of CodedOutputStream to remove any uninitialized
+ // memory from the Cord before we read it.
+ stream_.reset(NULL);
+ const void* data;
+ int length;
+ google::protobuf::io::ArrayInputStream input_stream(buffer_.data(), buffer_.size());
+ while (input_stream.Next(&data, &length)) {
+ if (length == 0) continue;
+ int num_bytes = length;
+ // Write up to where we need to insert the size field.
+ // The number of bytes we may write is the smaller of:
+ // - the current fragment size
+ // - the distance to the next position where a size field needs to be
+ // inserted.
+ if (!size_insert_.empty() &&
+ size_insert_.front().pos - curr_pos < num_bytes) {
+ num_bytes = size_insert_.front().pos - curr_pos;
+ }
+ output_->Append(static_cast<const char*>(data), num_bytes);
+ if (num_bytes < length) {
+ input_stream.BackUp(length - num_bytes);
+ }
+ curr_pos += num_bytes;
+ // Insert the size field.
+ // size_insert_.front(): the next <index, size> pair to be written.
+ // size_insert_.front().pos: position of the size field.
+ // size_insert_.front().size: the size (integer) to be inserted.
+ if (!size_insert_.empty() && curr_pos == size_insert_.front().pos) {
+ // Varint32 occupies at most 10 bytes.
+ uint8 insert_buffer[10];
+ uint8* insert_buffer_pos = CodedOutputStream::WriteVarint32ToArray(
+ size_insert_.front().size, insert_buffer);
+ output_->Append(reinterpret_cast<const char*>(insert_buffer),
+ insert_buffer_pos - insert_buffer);
+ size_insert_.pop_front();
+ }
+ }
+ output_->Flush();
+ stream_.reset(new CodedOutputStream(&adapter_));
+ done_ = true;
+}
+
+bool ProtoStreamObjectWriter::IsMap(const google::protobuf::Field& field) {
+ if (field.type_url().empty() ||
+ field.kind() != google::protobuf::Field_Kind_TYPE_MESSAGE ||
+ field.cardinality() !=
+ google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) {
+ return false;
+ }
+ const google::protobuf::Type* field_type =
+ typeinfo_->GetType(field.type_url());
+
+ return GetBoolOptionOrDefault(field_type->options(),
+ "google.protobuf.MessageOptions.map_entry", false);
+}
+
+void ProtoStreamObjectWriter::WriteTag(const google::protobuf::Field& field) {
+ WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType(
+ static_cast<WireFormatLite::FieldType>(field.kind()));
+ stream_->WriteTag(WireFormatLite::MakeTag(field.number(), wire_type));
+}
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h
new file mode 100644
index 00000000..eb4a59f9
--- /dev/null
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.h
@@ -0,0 +1,455 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__
+
+#include <deque>
+#include <google/protobuf/stubs/hash.h>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/util/internal/type_info.h>
+#include <google/protobuf/util/internal/datapiece.h>
+#include <google/protobuf/util/internal/error_listener.h>
+#include <google/protobuf/util/internal/structured_objectwriter.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/bytestream.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+class CodedOutputStream;
+} // namespace io
+} // namespace protobuf
+
+
+namespace protobuf {
+class Type;
+class Field;
+} // namespace protobuf
+
+
+namespace protobuf {
+namespace util {
+namespace converter {
+
+class ObjectLocationTracker;
+
+// An ObjectWriter that can write protobuf bytes directly from writer events.
+//
+// It also supports streaming.
+class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter {
+ public:
+ // Constructor. Does not take ownership of any parameter passed in.
+ ProtoStreamObjectWriter(TypeResolver* type_resolver,
+ const google::protobuf::Type& type,
+ strings::ByteSink* output, ErrorListener* listener);
+ virtual ~ProtoStreamObjectWriter();
+
+ // ObjectWriter methods.
+ virtual ProtoStreamObjectWriter* StartObject(StringPiece name);
+ virtual ProtoStreamObjectWriter* EndObject();
+ virtual ProtoStreamObjectWriter* StartList(StringPiece name);
+ virtual ProtoStreamObjectWriter* EndList();
+ virtual ProtoStreamObjectWriter* RenderBool(StringPiece name,
+ bool value) {
+ return RenderDataPiece(name, DataPiece(value));
+ }
+ virtual ProtoStreamObjectWriter* RenderInt32(StringPiece name,
+ int32 value) {
+ return RenderDataPiece(name, DataPiece(value));
+ }
+ virtual ProtoStreamObjectWriter* RenderUint32(StringPiece name,
+ uint32 value) {
+ return RenderDataPiece(name, DataPiece(value));
+ }
+ virtual ProtoStreamObjectWriter* RenderInt64(StringPiece name,
+ int64 value) {
+ return RenderDataPiece(name, DataPiece(value));
+ }
+ virtual ProtoStreamObjectWriter* RenderUint64(StringPiece name,
+ uint64 value) {
+ return RenderDataPiece(name, DataPiece(value));
+ }
+ virtual ProtoStreamObjectWriter* RenderDouble(StringPiece name,
+ double value) {
+ return RenderDataPiece(name, DataPiece(value));
+ }
+ virtual ProtoStreamObjectWriter* RenderFloat(StringPiece name,
+ float value) {
+ return RenderDataPiece(name, DataPiece(value));
+ }
+ virtual ProtoStreamObjectWriter* RenderString(StringPiece name,
+ StringPiece value) {
+ return RenderDataPiece(name, DataPiece(value));
+ }
+ virtual ProtoStreamObjectWriter* RenderBytes(StringPiece name,
+ StringPiece value) {
+ return RenderDataPiece(name, DataPiece(value, false));
+ }
+ virtual ProtoStreamObjectWriter* RenderNull(StringPiece name) {
+ return RenderDataPiece(name, DataPiece::NullData());
+ }
+
+ // Renders a DataPiece 'value' into a field whose wire type is determined
+ // from the given field 'name'.
+ ProtoStreamObjectWriter* RenderDataPiece(StringPiece name,
+ const DataPiece& value);
+
+ // Returns the location tracker to use for tracking locations for errors.
+ const LocationTrackerInterface& location() {
+ return element_ != NULL ? *element_ : *tracker_;
+ }
+
+ // When true, we finished writing to output a complete message.
+ bool done() const { return done_; }
+
+ private:
+ // Function that renders a well known type with modified behavior.
+ typedef util::Status (*TypeRenderer)(ProtoStreamObjectWriter*,
+ const DataPiece&);
+
+ // Handles writing Anys out using nested object writers and the like.
+ class LIBPROTOBUF_EXPORT AnyWriter {
+ public:
+ explicit AnyWriter(ProtoStreamObjectWriter* parent);
+ ~AnyWriter();
+
+ // Passes a StartObject call through to the Any writer.
+ void StartObject(StringPiece name);
+
+ // Passes an EndObject call through to the Any. Returns true if the any
+ // handled the EndObject call, false if the Any is now all done and is no
+ // longer needed.
+ bool EndObject();
+
+ // Passes a StartList call through to the Any writer.
+ void StartList(StringPiece name);
+
+ // Passes an EndList call through to the Any writer.
+ void EndList();
+
+ // Renders a data piece on the any.
+ void RenderDataPiece(StringPiece name, const DataPiece& value);
+
+ private:
+ // Handles starting up the any once we have a type.
+ void StartAny(const DataPiece& value);
+
+ // Writes the Any out to the parent writer in its serialized form.
+ void WriteAny();
+
+ // The parent of this writer, needed for various bits such as type info and
+ // the listeners.
+ ProtoStreamObjectWriter* parent_;
+
+ // The nested object writer, used to write events.
+ google::protobuf::scoped_ptr<ProtoStreamObjectWriter> ow_;
+
+ // The type_url_ that this Any represents.
+ string type_url_;
+
+ // Whether this any is invalid. This allows us to only report an invalid
+ // Any message a single time rather than every time we get a nested field.
+ bool invalid_;
+
+ // The output data and wrapping ByteSink.
+ string data_;
+ strings::StringByteSink output_;
+
+ // The depth within the Any, so we can track when we're done.
+ int depth_;
+
+ // True if the message type contained in Any has a special "value" message
+ // injected. This is true for well-known message types like Any or Struct.
+ bool has_injected_value_message_;
+ };
+
+ class LIBPROTOBUF_EXPORT ProtoElement : public BaseElement, public LocationTrackerInterface {
+ public:
+ // Indicates the type of element. Special types like LIST, MAP, MAP_ENTRY,
+ // STRUCT etc. are used to deduce other information based on their position
+ // on the stack of elements.
+ enum ElementType {
+ MESSAGE, // Simple message
+ LIST, // List/repeated element
+ MAP, // Proto3 map type
+ MAP_ENTRY, // Proto3 map message type, with 'key' and 'value' fields
+ ANY, // Proto3 Any type
+ STRUCT, // Proto3 struct type
+ STRUCT_VALUE, // Struct's Value message type
+ STRUCT_LIST, // List type indicator within a struct
+ STRUCT_LIST_VALUE, // Struct Value's ListValue message type
+ STRUCT_MAP, // Struct within a struct type
+ STRUCT_MAP_ENTRY // Struct map's entry type with 'key' and 'value'
+ // fields
+ };
+
+ // Constructor for the root element. No parent nor field.
+ ProtoElement(TypeInfo* typeinfo, const google::protobuf::Type& type,
+ ProtoStreamObjectWriter* enclosing);
+
+ // Constructor for a field of an element.
+ ProtoElement(ProtoElement* parent, const google::protobuf::Field* field,
+ const google::protobuf::Type& type, ElementType element_type);
+
+ virtual ~ProtoElement() {}
+
+ // Called just before the destructor for clean up:
+ // - reports any missing required fields
+ // - computes the space needed by the size field, and augment the
+ // length of all parent messages by this additional space.
+ // - releases and returns the parent pointer.
+ ProtoElement* pop();
+
+ // Accessors
+ const google::protobuf::Field* field() const { return field_; }
+ const google::protobuf::Type& type() const { return type_; }
+
+ // These functions return true if the element type is corresponding to the
+ // type in function name.
+ bool IsMap() { return element_type_ == MAP; }
+ bool IsStructMap() { return element_type_ == STRUCT_MAP; }
+ bool IsStructMapEntry() { return element_type_ == STRUCT_MAP_ENTRY; }
+ bool IsStructList() { return element_type_ == STRUCT_LIST; }
+ bool IsAny() { return element_type_ == ANY; }
+
+ ElementType element_type() { return element_type_; }
+
+ void RegisterField(const google::protobuf::Field* field);
+ virtual string ToString() const;
+
+ AnyWriter* any() const { return any_.get(); }
+
+ virtual ProtoElement* parent() const {
+ return static_cast<ProtoElement*>(BaseElement::parent());
+ }
+
+ private:
+ // Used for access to variables of the enclosing instance of
+ // ProtoStreamObjectWriter.
+ ProtoStreamObjectWriter* ow_;
+
+ // A writer for Any objects, handles all Any-related nonsense.
+ google::protobuf::scoped_ptr<AnyWriter> any_;
+
+ // Describes the element as a field in the parent message.
+ // field_ is NULL if and only if this element is the root element.
+ const google::protobuf::Field* field_;
+
+ // TypeInfo to lookup types.
+ TypeInfo* typeinfo_;
+
+ // Additional variables if this element is a message:
+ // (Root element is always a message).
+ // descriptor_ : describes allowed fields in the message.
+ // required_fields_: set of required fields.
+ // is_repeated_type_ : true if the element is of type list or map.
+ // size_index_ : index into ProtoStreamObjectWriter::size_insert_
+ // for later insertion of serialized message length.
+ const google::protobuf::Type& type_;
+ std::set<const google::protobuf::Field*> required_fields_;
+ const bool is_repeated_type_;
+ const int size_index_;
+
+ // Tracks position in repeated fields, needed for LocationTrackerInterface.
+ int array_index_;
+
+ // The type of this element, see enum for permissible types.
+ ElementType element_type_;
+
+ GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoElement);
+ };
+
+ // Container for inserting 'size' information at the 'pos' position.
+ struct SizeInfo {
+ const int pos;
+ int size;
+ };
+
+ ProtoStreamObjectWriter(TypeInfo* typeinfo,
+ const google::protobuf::Type& type,
+ strings::ByteSink* output, ErrorListener* listener);
+
+ ProtoElement* element() { return element_.get(); }
+
+ // Helper methods for calling ErrorListener. See error_listener.h.
+ void InvalidName(StringPiece unknown_name, StringPiece message);
+ void InvalidValue(StringPiece type_name, StringPiece value);
+ void MissingField(StringPiece missing_name);
+
+ // Common code for BeginObject() and BeginList() that does invalid_depth_
+ // bookkeeping associated with name lookup.
+ const google::protobuf::Field* BeginNamed(StringPiece name, bool is_list);
+
+ // Lookup the field in the current element. Looks in the base descriptor
+ // and in any extension. This will report an error if the field cannot be
+ // found or if multiple matching extensions are found.
+ const google::protobuf::Field* Lookup(StringPiece name);
+
+ // Lookup the field type in the type descriptor. Returns NULL if the type
+ // is not known.
+ const google::protobuf::Type* LookupType(
+ const google::protobuf::Field* field);
+
+ // Looks up the oneof struct Value field depending on the type.
+ // On failure to find, it returns an appropriate error.
+ util::StatusOr<const google::protobuf::Field*> LookupStructField(
+ DataPiece::Type type);
+
+ // Starts an entry in map. This will be called after placing map element at
+ // the top of the stack. Uses this information to write map entries.
+ const google::protobuf::Field* StartMapEntry(StringPiece name);
+
+ // Starts a google.protobuf.Struct.
+ // 'field' is of type google.protobuf.Struct.
+ // If field is NULL, it indicates that the top-level message is a struct
+ // type.
+ void StartStruct(const google::protobuf::Field* field);
+
+ // Starts another struct within a struct.
+ // 'field' is of type google.protobuf.Value (see struct.proto).
+ const google::protobuf::Field* StartStructValueInStruct(
+ const google::protobuf::Field* field);
+
+ // Starts a list within a struct.
+ // 'field' is of type google.protobuf.ListValue (see struct.proto).
+ const google::protobuf::Field* StartListValueInStruct(
+ const google::protobuf::Field* field);
+
+ // Starts the repeated "values" field in struct.proto's
+ // google.protobuf.ListValue type. 'field' should be of type
+ // google.protobuf.ListValue.
+ const google::protobuf::Field* StartRepeatedValuesInListValue(
+ const google::protobuf::Field* field);
+
+ // Pops sentinel elements off the stack.
+ void SkipElements();
+
+ // Write serialized output to the final output ByteSink, inserting all
+ // the size information for nested messages that are missing from the
+ // intermediate Cord buffer.
+ void WriteRootMessage();
+
+ // Returns true if the field is a map.
+ bool IsMap(const google::protobuf::Field& field);
+
+ // Returns true if the field is an any.
+ bool IsAny(const google::protobuf::Field& field);
+
+ // Helper method to write proto tags based on the given field.
+ void WriteTag(const google::protobuf::Field& field);
+
+ // Helper function to render primitive data types in DataPiece.
+ void RenderSimpleDataPiece(const google::protobuf::Field& field,
+ const google::protobuf::Type& type,
+ const DataPiece& data);
+
+ // Renders google.protobuf.Value in struct.proto. It picks the right oneof
+ // type based on value's type.
+ static util::Status RenderStructValue(ProtoStreamObjectWriter* ow,
+ const DataPiece& value);
+
+ // Renders google.protobuf.Timestamp value.
+ static util::Status RenderTimestamp(ProtoStreamObjectWriter* ow,
+ const DataPiece& value);
+
+ // Renders google.protobuf.FieldMask value.
+ static util::Status RenderFieldMask(ProtoStreamObjectWriter* ow,
+ const DataPiece& value);
+
+ // Renders google.protobuf.Duration value.
+ static util::Status RenderDuration(ProtoStreamObjectWriter* ow,
+ const DataPiece& value);
+
+ // Renders wrapper message types for primitive types in
+ // google/protobuf/wrappers.proto.
+ static util::Status RenderWrapperType(ProtoStreamObjectWriter* ow,
+ const DataPiece& value);
+
+ // Helper functions to create the map and find functions responsible for
+ // rendering well known types, keyed by type URL.
+ static hash_map<string, TypeRenderer>* CreateRendererMap();
+ static TypeRenderer* FindTypeRenderer(const string& type_url);
+
+ // Returns the ProtoElement::ElementType for the given Type.
+ static ProtoElement::ElementType GetElementType(
+ const google::protobuf::Type& type);
+
+ // Variables for describing the structure of the input tree:
+ // master_type_: descriptor for the whole protobuf message.
+ // typeinfo_ : the TypeInfo object to lookup types.
+ const google::protobuf::Type& master_type_;
+ TypeInfo* typeinfo_;
+ // Whether we own the typeinfo_ object.
+ bool own_typeinfo_;
+
+ // Indicates whether we finished writing root message completely.
+ bool done_;
+
+ // Variable for internal state processing:
+ // element_ : the current element.
+ // size_insert_: sizes of nested messages.
+ // pos - position to insert the size field.
+ // size - size value to be inserted.
+ google::protobuf::scoped_ptr<ProtoElement> element_;
+ std::deque<SizeInfo> size_insert_;
+
+ // Variables for output generation:
+ // output_ : pointer to an external ByteSink for final user-visible output.
+ // buffer_ : buffer holding partial message before being ready for output_.
+ // adapter_ : internal adapter between CodedOutputStream and Cord buffer_.
+ // stream_ : wrapper for writing tags and other encodings in wire format.
+ strings::ByteSink* output_;
+ string buffer_;
+ google::protobuf::io::StringOutputStream adapter_;
+ google::protobuf::scoped_ptr<google::protobuf::io::CodedOutputStream> stream_;
+
+ // Variables for error tracking and reporting:
+ // listener_ : a place to report any errors found.
+ // invalid_depth_: number of enclosing invalid nested messages.
+ // tracker_ : the root location tracker interface.
+ ErrorListener* listener_;
+ int invalid_depth_;
+ google::protobuf::scoped_ptr<LocationTrackerInterface> tracker_;
+
+ GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectWriter);
+};
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
new file mode 100644
index 00000000..bd4f29f5
--- /dev/null
+++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
@@ -0,0 +1,1513 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/protostream_objectwriter.h>
+
+#include <stddef.h> // For size_t
+
+#include <google/protobuf/field_mask.pb.h>
+#include <google/protobuf/timestamp.pb.h>
+#include <google/protobuf/wrappers.pb.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/util/internal/mock_error_listener.h>
+#include <google/protobuf/util/internal/testdata/books.pb.h>
+#include <google/protobuf/util/internal/testdata/field_mask.pb.h>
+#include <google/protobuf/util/internal/type_info_test_helper.h>
+#include <google/protobuf/util/internal/constants.h>
+#include <google/protobuf/stubs/bytestream.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/util/internal/testdata/anys.pb.h>
+#include <google/protobuf/util/internal/testdata/maps.pb.h>
+#include <google/protobuf/util/internal/testdata/struct.pb.h>
+#include <google/protobuf/util/internal/testdata/timestamp_duration.pb.h>
+#include <gtest/gtest.h>
+
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+using google::protobuf::testing::Author;
+using google::protobuf::testing::Book;
+using google::protobuf::testing::Book_Data;
+using google::protobuf::testing::Primitive;
+using google::protobuf::testing::Publisher;
+using google::protobuf::Descriptor;
+using google::protobuf::DescriptorPool;
+using google::protobuf::DynamicMessageFactory;
+using google::protobuf::FileDescriptorProto;
+using google::protobuf::Message;
+using google::protobuf::io::ArrayInputStream;
+using strings::GrowingArrayByteSink;
+using ::testing::_;
+using ::testing::Args;
+using google::protobuf::testing::anys::AnyM;
+using google::protobuf::testing::anys::AnyOut;
+using google::protobuf::testing::FieldMaskTest;
+using google::protobuf::testing::maps::MapIn;
+using google::protobuf::testing::structs::StructType;
+using google::protobuf::testing::timestampduration::TimestampDuration;
+
+
+namespace {
+string GetTypeUrl(const Descriptor* descriptor) {
+ return string(kTypeServiceBaseUrl) + "/" + descriptor->full_name();
+}
+} // namespace
+
+class BaseProtoStreamObjectWriterTest
+ : public ::testing::TestWithParam<testing::TypeInfoSource> {
+ protected:
+ BaseProtoStreamObjectWriterTest()
+ : helper_(GetParam()),
+ listener_(),
+ output_(new GrowingArrayByteSink(1000)),
+ ow_() {}
+
+ explicit BaseProtoStreamObjectWriterTest(const Descriptor* descriptor)
+ : helper_(GetParam()),
+ listener_(),
+ output_(new GrowingArrayByteSink(1000)),
+ ow_() {
+ vector<const Descriptor*> descriptors;
+ descriptors.push_back(descriptor);
+ ResetTypeInfo(descriptors);
+ }
+
+ explicit BaseProtoStreamObjectWriterTest(
+ vector<const Descriptor*> descriptors)
+ : helper_(GetParam()),
+ listener_(),
+ output_(new GrowingArrayByteSink(1000)),
+ ow_() {
+ ResetTypeInfo(descriptors);
+ }
+
+ void ResetTypeInfo(vector<const Descriptor*> descriptors) {
+ GOOGLE_CHECK(!descriptors.empty()) << "Must have at least one descriptor!";
+ helper_.ResetTypeInfo(descriptors);
+ ow_.reset(helper_.NewProtoWriter(GetTypeUrl(descriptors[0]), output_.get(),
+ &listener_));
+ }
+
+ virtual ~BaseProtoStreamObjectWriterTest() {}
+
+ void CheckOutput(const Message& expected, int expected_length) {
+ size_t nbytes;
+ google::protobuf::scoped_array<char> buffer(output_->GetBuffer(&nbytes));
+ if (expected_length >= 0) {
+ EXPECT_EQ(expected_length, nbytes);
+ }
+ string str(buffer.get(), nbytes);
+
+ std::stringbuf str_buf(str, std::ios_base::in);
+ std::istream istream(&str_buf);
+ google::protobuf::scoped_ptr<Message> message(expected.New());
+ message->ParsePartialFromIstream(&istream);
+
+ EXPECT_EQ(expected.DebugString(), message->DebugString());
+ }
+
+ void CheckOutput(const Message& expected) { CheckOutput(expected, -1); }
+
+ const google::protobuf::Type* GetType(const Descriptor* descriptor) {
+ return helper_.GetTypeInfo()->GetType(GetTypeUrl(descriptor));
+ }
+
+ testing::TypeInfoTestHelper helper_;
+ MockErrorListener listener_;
+ google::protobuf::scoped_ptr<GrowingArrayByteSink> output_;
+ google::protobuf::scoped_ptr<ProtoStreamObjectWriter> ow_;
+};
+
+MATCHER_P(HasObjectLocation, expected,
+ "Verifies the expected object location") {
+ string actual = std::tr1::get<0>(arg).ToString();
+ if (actual.compare(expected) == 0) return true;
+ *result_listener << "actual location is: " << actual;
+ return false;
+}
+
+class ProtoStreamObjectWriterTest : public BaseProtoStreamObjectWriterTest {
+ protected:
+ ProtoStreamObjectWriterTest()
+ : BaseProtoStreamObjectWriterTest(Book::descriptor()) {}
+
+ virtual ~ProtoStreamObjectWriterTest() {}
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+ ProtoStreamObjectWriterTest,
+ ::testing::Values(
+ testing::USE_TYPE_RESOLVER));
+
+TEST_P(ProtoStreamObjectWriterTest, EmptyObject) {
+ Book empty;
+ ow_->StartObject("")->EndObject();
+ CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, SimpleObject) {
+ string content("My content");
+
+ Book book;
+ book.set_title("My Title");
+ book.set_length(222);
+ book.set_content(content);
+
+ ow_->StartObject("")
+ ->RenderString("title", "My Title")
+ ->RenderInt32("length", 222)
+ ->RenderBytes("content", content)
+ ->EndObject();
+ CheckOutput(book);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, SimpleMessage) {
+ Book book;
+ book.set_title("Some Book");
+ book.set_length(102);
+ Publisher* publisher = book.mutable_publisher();
+ publisher->set_name("My Publisher");
+ Author* robert = book.mutable_author();
+ robert->set_alive(true);
+ robert->set_name("robert");
+ robert->add_pseudonym("bob");
+ robert->add_pseudonym("bobby");
+ robert->add_friend_()->set_name("john");
+
+ ow_->StartObject("")
+ ->RenderString("title", "Some Book")
+ ->RenderInt32("length", 102)
+ ->StartObject("publisher")
+ ->RenderString("name", "My Publisher")
+ ->EndObject()
+ ->StartObject("author")
+ ->RenderBool("alive", true)
+ ->RenderString("name", "robert")
+ ->StartList("pseudonym")
+ ->RenderString("", "bob")
+ ->RenderString("", "bobby")
+ ->EndList()
+ ->StartList("friend")
+ ->StartObject("")
+ ->RenderString("name", "john")
+ ->EndObject()
+ ->EndList()
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(book);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, PrimitiveFromStringConversion) {
+ Primitive full;
+ full.set_fix32(101);
+ full.set_u32(102);
+ full.set_i32(-103);
+ full.set_sf32(-104);
+ full.set_s32(-105);
+ full.set_fix64(40000000001L);
+ full.set_u64(40000000002L);
+ full.set_i64(-40000000003L);
+ full.set_sf64(-40000000004L);
+ full.set_s64(-40000000005L);
+ full.set_str("string1");
+ full.set_bytes("Some Bytes");
+ full.set_float_(3.14f);
+ full.set_double_(-4.05L);
+ full.set_bool_(true);
+ full.add_rep_fix32(201);
+ full.add_rep_u32(202);
+ full.add_rep_i32(-203);
+ full.add_rep_sf32(-204);
+ full.add_rep_s32(-205);
+ full.add_rep_fix64(80000000001L);
+ full.add_rep_u64(80000000002L);
+ full.add_rep_i64(-80000000003L);
+ full.add_rep_sf64(-80000000004L);
+ full.add_rep_s64(-80000000005L);
+ full.add_rep_str("string2");
+ full.add_rep_bytes("More Bytes");
+ full.add_rep_float(6.14f);
+ full.add_rep_double(-8.05L);
+ full.add_rep_bool(false);
+
+ ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()),
+ output_.get(), &listener_));
+
+ ow_->StartObject("")
+ ->RenderString("fix32", "101")
+ ->RenderString("u32", "102")
+ ->RenderString("i32", "-103")
+ ->RenderString("sf32", "-104")
+ ->RenderString("s32", "-105")
+ ->RenderString("fix64", "40000000001")
+ ->RenderString("u64", "40000000002")
+ ->RenderString("i64", "-40000000003")
+ ->RenderString("sf64", "-40000000004")
+ ->RenderString("s64", "-40000000005")
+ ->RenderString("str", "string1")
+ ->RenderString("bytes", "U29tZSBCeXRlcw==") // "Some Bytes"
+ ->RenderString("float", "3.14")
+ ->RenderString("double", "-4.05")
+ ->RenderString("bool", "true")
+ ->StartList("rep_fix32")
+ ->RenderString("", "201")
+ ->EndList()
+ ->StartList("rep_u32")
+ ->RenderString("", "202")
+ ->EndList()
+ ->StartList("rep_i32")
+ ->RenderString("", "-203")
+ ->EndList()
+ ->StartList("rep_sf32")
+ ->RenderString("", "-204")
+ ->EndList()
+ ->StartList("rep_s32")
+ ->RenderString("", "-205")
+ ->EndList()
+ ->StartList("rep_fix64")
+ ->RenderString("", "80000000001")
+ ->EndList()
+ ->StartList("rep_u64")
+ ->RenderString("", "80000000002")
+ ->EndList()
+ ->StartList("rep_i64")
+ ->RenderString("", "-80000000003")
+ ->EndList()
+ ->StartList("rep_sf64")
+ ->RenderString("", "-80000000004")
+ ->EndList()
+ ->StartList("rep_s64")
+ ->RenderString("", "-80000000005")
+ ->EndList()
+ ->StartList("rep_str")
+ ->RenderString("", "string2")
+ ->EndList()
+ ->StartList("rep_bytes")
+ ->RenderString("", "TW9yZSBCeXRlcw==") // "More Bytes"
+ ->EndList()
+ ->StartList("rep_float")
+ ->RenderString("", "6.14")
+ ->EndList()
+ ->StartList("rep_double")
+ ->RenderString("", "-8.05")
+ ->EndList()
+ ->StartList("rep_bool")
+ ->RenderString("", "false")
+ ->EndList()
+ ->EndObject();
+ CheckOutput(full);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, InfinityInputTest) {
+ Primitive full;
+ full.set_double_(std::numeric_limits<double>::infinity());
+ full.set_float_(std::numeric_limits<float>::infinity());
+ full.set_str("-Infinity");
+
+ ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()),
+ output_.get(), &listener_));
+
+ EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"),
+ StringPiece("\"Infinity\"")))
+ .With(Args<0>(HasObjectLocation("i32")));
+ EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
+ StringPiece("\"Infinity\"")))
+ .With(Args<0>(HasObjectLocation("u32")));
+ EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_SFIXED64"),
+ StringPiece("\"-Infinity\"")))
+ .With(Args<0>(HasObjectLocation("sf64")));
+ EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_BOOL"),
+ StringPiece("\"Infinity\"")))
+ .With(Args<0>(HasObjectLocation("bool")));
+
+ ow_->StartObject("")
+ ->RenderString("double", "Infinity")
+ ->RenderString("float", "Infinity")
+ ->RenderString("i32", "Infinity")
+ ->RenderString("u32", "Infinity")
+ ->RenderString("sf64", "-Infinity")
+ ->RenderString("str", "-Infinity")
+ ->RenderString("bool", "Infinity")
+ ->EndObject();
+ CheckOutput(full);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, NaNInputTest) {
+ Primitive full;
+ full.set_double_(std::numeric_limits<double>::quiet_NaN());
+ full.set_float_(std::numeric_limits<float>::quiet_NaN());
+ full.set_str("NaN");
+
+ ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()),
+ output_.get(), &listener_));
+
+ EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"),
+ StringPiece("\"NaN\"")))
+ .With(Args<0>(HasObjectLocation("i32")));
+ EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
+ StringPiece("\"NaN\"")))
+ .With(Args<0>(HasObjectLocation("u32")));
+ EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_SFIXED64"),
+ StringPiece("\"NaN\"")))
+ .With(Args<0>(HasObjectLocation("sf64")));
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("TYPE_BOOL"), StringPiece("\"NaN\"")))
+ .With(Args<0>(HasObjectLocation("bool")));
+
+ ow_->StartObject("")
+ ->RenderString("double", "NaN")
+ ->RenderString("float", "NaN")
+ ->RenderString("i32", "NaN")
+ ->RenderString("u32", "NaN")
+ ->RenderString("sf64", "NaN")
+ ->RenderString("str", "NaN")
+ ->RenderString("bool", "NaN")
+ ->EndObject();
+
+ CheckOutput(full);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, ImplicitPrimitiveList) {
+ Book expected;
+ Author* author = expected.mutable_author();
+ author->set_name("The Author");
+ author->add_pseudonym("first");
+ author->add_pseudonym("second");
+
+ ow_->StartObject("")
+ ->StartObject("author")
+ ->RenderString("name", "The Author")
+ ->RenderString("pseudonym", "first")
+ ->RenderString("pseudonym", "second")
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest,
+ LastWriteWinsOnNonRepeatedPrimitiveFieldWithDuplicates) {
+ Book expected;
+ Author* author = expected.mutable_author();
+ author->set_name("second");
+
+ ow_->StartObject("")
+ ->StartObject("author")
+ ->RenderString("name", "first")
+ ->RenderString("name", "second")
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, ExplicitPrimitiveList) {
+ Book expected;
+ Author* author = expected.mutable_author();
+ author->set_name("The Author");
+ author->add_pseudonym("first");
+ author->add_pseudonym("second");
+
+ ow_->StartObject("")
+ ->StartObject("author")
+ ->RenderString("name", "The Author")
+ ->StartList("pseudonym")
+ ->RenderString("", "first")
+ ->RenderString("", "second")
+ ->EndList()
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, NonRepeatedExplicitPrimitiveList) {
+ Book expected;
+ expected.set_allocated_author(new Author());
+
+ EXPECT_CALL(
+ listener_,
+ InvalidName(
+ _, StringPiece("name"),
+ StringPiece("Proto field is not repeating, cannot start list.")))
+ .With(Args<0>(HasObjectLocation("author")));
+ ow_->StartObject("")
+ ->StartObject("author")
+ ->StartList("name")
+ ->RenderString("", "first")
+ ->RenderString("", "second")
+ ->EndList()
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, ImplicitMessageList) {
+ Book expected;
+ Author* outer = expected.mutable_author();
+ outer->set_name("outer");
+ outer->set_alive(true);
+ Author* first = outer->add_friend_();
+ first->set_name("first");
+ Author* second = outer->add_friend_();
+ second->set_name("second");
+
+ ow_->StartObject("")
+ ->StartObject("author")
+ ->RenderString("name", "outer")
+ ->RenderBool("alive", true)
+ ->StartObject("friend")
+ ->RenderString("name", "first")
+ ->EndObject()
+ ->StartObject("friend")
+ ->RenderString("name", "second")
+ ->EndObject()
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest,
+ LastWriteWinsOnNonRepeatedMessageFieldWithDuplicates) {
+ Book expected;
+ Author* author = expected.mutable_author();
+ author->set_name("The Author");
+ Publisher* publisher = expected.mutable_publisher();
+ publisher->set_name("second");
+
+ ow_->StartObject("")
+ ->StartObject("author")
+ ->RenderString("name", "The Author")
+ ->EndObject()
+ ->StartObject("publisher")
+ ->RenderString("name", "first")
+ ->EndObject()
+ ->StartObject("publisher")
+ ->RenderString("name", "second")
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, ExplicitMessageList) {
+ Book expected;
+ Author* outer = expected.mutable_author();
+ outer->set_name("outer");
+ outer->set_alive(true);
+ Author* first = outer->add_friend_();
+ first->set_name("first");
+ Author* second = outer->add_friend_();
+ second->set_name("second");
+
+ ow_->StartObject("")
+ ->StartObject("author")
+ ->RenderString("name", "outer")
+ ->RenderBool("alive", true)
+ ->StartList("friend")
+ ->StartObject("")
+ ->RenderString("name", "first")
+ ->EndObject()
+ ->StartObject("")
+ ->RenderString("name", "second")
+ ->EndObject()
+ ->EndList()
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, NonRepeatedExplicitMessageList) {
+ Book expected;
+ Author* author = expected.mutable_author();
+ author->set_name("The Author");
+
+ EXPECT_CALL(
+ listener_,
+ InvalidName(
+ _, StringPiece("publisher"),
+ StringPiece("Proto field is not repeating, cannot start list.")))
+ .With(Args<0>(HasObjectLocation("")));
+ ow_->StartObject("")
+ ->StartObject("author")
+ ->RenderString("name", "The Author")
+ ->EndObject()
+ ->StartList("publisher")
+ ->StartObject("")
+ ->RenderString("name", "first")
+ ->EndObject()
+ ->StartObject("")
+ ->RenderString("name", "second")
+ ->EndObject()
+ ->EndList()
+ ->EndObject();
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnknownFieldAtRoot) {
+ Book empty;
+
+ EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
+ StringPiece("Cannot find field.")))
+ .With(Args<0>(HasObjectLocation("")));
+ ow_->StartObject("")->RenderString("unknown", "Nope!")->EndObject();
+ CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnknownFieldAtAuthorFriend) {
+ Book expected;
+ Author* paul = expected.mutable_author();
+ paul->set_name("Paul");
+ Author* mark = paul->add_friend_();
+ mark->set_name("Mark");
+ Author* john = paul->add_friend_();
+ john->set_name("John");
+ Author* luke = paul->add_friend_();
+ luke->set_name("Luke");
+
+ EXPECT_CALL(listener_, InvalidName(_, StringPiece("address"),
+ StringPiece("Cannot find field.")))
+ .With(Args<0>(HasObjectLocation("author.friend[1]")));
+ ow_->StartObject("")
+ ->StartObject("author")
+ ->RenderString("name", "Paul")
+ ->StartList("friend")
+ ->StartObject("")
+ ->RenderString("name", "Mark")
+ ->EndObject()
+ ->StartObject("")
+ ->RenderString("name", "John")
+ ->RenderString("address", "Patmos")
+ ->EndObject()
+ ->StartObject("")
+ ->RenderString("name", "Luke")
+ ->EndObject()
+ ->EndList()
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnknownObjectAtRoot) {
+ Book empty;
+
+ EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
+ StringPiece("Cannot find field.")))
+ .With(Args<0>(HasObjectLocation("")));
+ ow_->StartObject("")->StartObject("unknown")->EndObject()->EndObject();
+ CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnknownObjectAtAuthor) {
+ Book expected;
+ Author* author = expected.mutable_author();
+ author->set_name("William");
+ author->add_pseudonym("Bill");
+
+ EXPECT_CALL(listener_, InvalidName(_, StringPiece("wife"),
+ StringPiece("Cannot find field.")))
+ .With(Args<0>(HasObjectLocation("author")));
+ ow_->StartObject("")
+ ->StartObject("author")
+ ->RenderString("name", "William")
+ ->StartObject("wife")
+ ->RenderString("name", "Hilary")
+ ->EndObject()
+ ->RenderString("pseudonym", "Bill")
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnknownListAtRoot) {
+ Book empty;
+
+ EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
+ StringPiece("Cannot find field.")))
+ .With(Args<0>(HasObjectLocation("")));
+ ow_->StartObject("")->StartList("unknown")->EndList()->EndObject();
+ CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnknownListAtPublisher) {
+ Book expected;
+ expected.set_title("Brainwashing");
+ Publisher* publisher = expected.mutable_publisher();
+ publisher->set_name("propaganda");
+
+ EXPECT_CALL(listener_, InvalidName(_, StringPiece("alliance"),
+ StringPiece("Cannot find field.")))
+ .With(Args<0>(HasObjectLocation("publisher")));
+ ow_->StartObject("")
+ ->StartObject("publisher")
+ ->RenderString("name", "propaganda")
+ ->StartList("alliance")
+ ->EndList()
+ ->EndObject()
+ ->RenderString("title", "Brainwashing")
+ ->EndObject();
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, MissingRequiredField) {
+ Book expected;
+ expected.set_title("My Title");
+ expected.set_allocated_publisher(new Publisher());
+
+ EXPECT_CALL(listener_, MissingField(_, StringPiece("name")))
+ .With(Args<0>(HasObjectLocation("publisher")));
+ ow_->StartObject("")
+ ->StartObject("publisher")
+ ->EndObject()
+ ->RenderString("title", "My Title")
+ ->EndObject();
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, InvalidFieldValueAtRoot) {
+ Book empty;
+
+ EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
+ StringPiece("\"garbage\"")))
+ .With(Args<0>(HasObjectLocation("length")));
+ ow_->StartObject("")->RenderString("length", "garbage")->EndObject();
+ CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, MultipleInvalidFieldValues) {
+ Book expected;
+ expected.set_title("My Title");
+
+ EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
+ StringPiece("\"-400\"")))
+ .With(Args<0>(HasObjectLocation("length")));
+ EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT64"),
+ StringPiece("\"3.14\"")))
+ .With(Args<0>(HasObjectLocation("published")));
+ ow_->StartObject("")
+ ->RenderString("length", "-400")
+ ->RenderString("published", "3.14")
+ ->RenderString("title", "My Title")
+ ->EndObject();
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnnamedFieldAtRoot) {
+ Book empty;
+
+ EXPECT_CALL(listener_,
+ InvalidName(_, StringPiece(""),
+ StringPiece("Proto fields must have a name.")))
+ .With(Args<0>(HasObjectLocation("")));
+ ow_->StartObject("")->RenderFloat("", 3.14)->EndObject();
+ CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnnamedFieldAtAuthor) {
+ Book expected;
+ expected.set_title("noname");
+ expected.set_allocated_author(new Author());
+
+ EXPECT_CALL(listener_,
+ InvalidName(_, StringPiece(""),
+ StringPiece("Proto fields must have a name.")))
+ .With(Args<0>(HasObjectLocation("author")));
+ ow_->StartObject("")
+ ->StartObject("author")
+ ->RenderInt32("", 123)
+ ->EndObject()
+ ->RenderString("title", "noname")
+ ->EndObject();
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, UnnamedListAtRoot) {
+ Book expected;
+ expected.set_title("noname");
+
+ EXPECT_CALL(listener_,
+ InvalidName(_, StringPiece(""),
+ StringPiece("Proto fields must have a name.")))
+ .With(Args<0>(HasObjectLocation("")));
+ ow_->StartObject("")
+ ->StartList("")
+ ->EndList()
+ ->RenderString("title", "noname")
+ ->EndObject();
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, RootNamedObject) {
+ Book expected;
+ expected.set_title("Annie");
+
+ EXPECT_CALL(listener_,
+ InvalidName(_, StringPiece("oops"),
+ StringPiece("Root element should not be named.")))
+ .With(Args<0>(HasObjectLocation("")));
+ ow_->StartObject("oops")->RenderString("title", "Annie")->EndObject();
+ CheckOutput(expected, 7);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, RootNamedList) {
+ Book empty;
+
+ EXPECT_CALL(listener_,
+ InvalidName(_, StringPiece("oops"),
+ StringPiece("Root element should not be named.")))
+ .With(Args<0>(HasObjectLocation("")));
+ EXPECT_CALL(listener_,
+ InvalidName(_, StringPiece(""),
+ StringPiece("Proto fields must have a name.")))
+ .With(Args<0>(HasObjectLocation("")));
+ ow_->StartList("oops")->RenderString("", "item")->EndList();
+ CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, RootUnnamedField) {
+ Book empty;
+
+ EXPECT_CALL(listener_,
+ InvalidName(_, StringPiece(""),
+ StringPiece("Root element must be a message.")))
+ .With(Args<0>(HasObjectLocation("")));
+ ow_->RenderBool("", true);
+ CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, RootNamedField) {
+ Book empty;
+
+ EXPECT_CALL(listener_,
+ InvalidName(_, StringPiece("oops"),
+ StringPiece("Root element must be a message.")))
+ .With(Args<0>(HasObjectLocation("")));
+ ow_->RenderBool("oops", true);
+ CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, NullValue) {
+ Book empty;
+
+ ow_->RenderNull("");
+ CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, NullValueForMessageField) {
+ Book empty;
+
+ ow_->RenderNull("author");
+ CheckOutput(empty, 0);
+}
+
+TEST_P(ProtoStreamObjectWriterTest, NullValueForPrimitiveField) {
+ Book empty;
+
+ ow_->RenderNull("length");
+ CheckOutput(empty, 0);
+}
+
+class ProtoStreamObjectWriterTimestampDurationTest
+ : public BaseProtoStreamObjectWriterTest {
+ protected:
+ ProtoStreamObjectWriterTimestampDurationTest() {
+ vector<const Descriptor*> descriptors;
+ descriptors.push_back(TimestampDuration::descriptor());
+ descriptors.push_back(google::protobuf::Timestamp::descriptor());
+ descriptors.push_back(google::protobuf::Duration::descriptor());
+ ResetTypeInfo(descriptors);
+ }
+};
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError1) {
+ TimestampDuration timestamp;
+
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+ StringPiece(
+ "Field 'ts', Illegal timestamp format; timestamps "
+ "must end with 'Z'")));
+
+ ow_->StartObject("")->RenderString("ts", "")->EndObject();
+ CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError2) {
+ TimestampDuration timestamp;
+
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+ StringPiece(
+ "Field 'ts', Invalid time format: Failed to parse input")));
+
+ ow_->StartObject("")->RenderString("ts", "Z")->EndObject();
+ CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError3) {
+ TimestampDuration timestamp;
+
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+ StringPiece(
+ "Field 'ts', Invalid time format, failed to parse nano "
+ "seconds")));
+
+ ow_->StartObject("")
+ ->RenderString("ts", "1970-01-01T00:00:00.ABZ")
+ ->EndObject();
+ CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError4) {
+ TimestampDuration timestamp;
+
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+ StringPiece("Field 'ts', Timestamp value exceeds limits")));
+
+ ow_->StartObject("")
+ ->RenderString("ts", "-8032-10-18T00:00:00.000Z")
+ ->EndObject();
+ CheckOutput(timestamp);
+}
+
+// TODO(skarvaje): Write a test for nanos that exceed limit. Currently, it is
+// not possible to construct a test case where nanos exceed limit because of
+// floating point arithmetic.
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError1) {
+ TimestampDuration duration;
+
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.Duration"),
+ StringPiece(
+ "Field 'dur', Illegal duration format; duration must "
+ "end with 's'")));
+
+ ow_->StartObject("")->RenderString("dur", "")->EndObject();
+ CheckOutput(duration);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError2) {
+ TimestampDuration duration;
+
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.Duration"),
+ StringPiece(
+ "Field 'dur', Invalid duration format, failed to parse "
+ "seconds")));
+
+ ow_->StartObject("")->RenderString("dur", "s")->EndObject();
+ CheckOutput(duration);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError3) {
+ TimestampDuration duration;
+
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.Duration"),
+ StringPiece(
+ "Field 'dur', Invalid duration format, failed to "
+ "parse nanos seconds")));
+
+ ow_->StartObject("")->RenderString("dur", "123.DEFs")->EndObject();
+ CheckOutput(duration);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError4) {
+ TimestampDuration duration;
+
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.Duration"),
+ StringPiece("Field 'dur', Duration value exceeds limits")));
+
+ ow_->StartObject("")->RenderString("dur", "315576000002s")->EndObject();
+ CheckOutput(duration);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+ MismatchedTimestampTypeInput) {
+ TimestampDuration timestamp;
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+ StringPiece(
+ "Field 'ts', Invalid data type for timestamp, value is null")))
+ .With(Args<0>(HasObjectLocation("ts")));
+ ow_->StartObject("")->RenderNull("ts")->EndObject();
+ CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+ MismatchedDurationTypeInput) {
+ TimestampDuration duration;
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
+ StringPiece(
+ "Field 'dur', Invalid data type for duration, value is null")))
+ .With(Args<0>(HasObjectLocation("dur")));
+ ow_->StartObject("")->RenderNull("dur")->EndObject();
+ CheckOutput(duration);
+}
+
+class ProtoStreamObjectWriterStructTest
+ : public BaseProtoStreamObjectWriterTest {
+ protected:
+ ProtoStreamObjectWriterStructTest() {
+ vector<const Descriptor*> descriptors;
+ descriptors.push_back(StructType::descriptor());
+ descriptors.push_back(google::protobuf::Struct::descriptor());
+ ResetTypeInfo(descriptors);
+ }
+};
+
+// TODO(skarvaje): Write tests for failure cases.
+TEST_P(ProtoStreamObjectWriterStructTest, StructRenderSuccess) {
+ StructType struct_type;
+ google::protobuf::Struct* s = struct_type.mutable_object();
+ s->mutable_fields()->operator[]("k1").set_number_value(123);
+ s->mutable_fields()->operator[]("k2").set_bool_value(true);
+
+ ow_->StartObject("")
+ ->StartObject("object")
+ ->RenderDouble("k1", 123)
+ ->RenderBool("k2", true)
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(struct_type);
+}
+
+TEST_P(ProtoStreamObjectWriterStructTest, StructNullInputSuccess) {
+ StructType struct_type;
+ EXPECT_CALL(listener_,
+ InvalidName(_, StringPiece(""),
+ StringPiece("Proto fields must have a name.")))
+ .With(Args<0>(HasObjectLocation("")));
+ ow_->StartObject("")->RenderNull("")->EndObject();
+ CheckOutput(struct_type);
+}
+
+TEST_P(ProtoStreamObjectWriterStructTest, StructInvalidInputFailure) {
+ StructType struct_type;
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_, StringPiece("type.googleapis.com/google.protobuf.Struct"),
+ StringPiece("true")))
+ .With(Args<0>(HasObjectLocation("object")));
+
+ ow_->StartObject("")->RenderBool("object", true)->EndObject();
+ CheckOutput(struct_type);
+}
+
+class ProtoStreamObjectWriterMapTest : public BaseProtoStreamObjectWriterTest {
+ protected:
+ ProtoStreamObjectWriterMapTest()
+ : BaseProtoStreamObjectWriterTest(MapIn::descriptor()) {}
+};
+
+TEST_P(ProtoStreamObjectWriterMapTest, MapShouldNotAcceptList) {
+ MapIn mm;
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("Map"),
+ StringPiece("Cannot bind a list to map.")))
+ .With(Args<0>(HasObjectLocation("map_input")));
+ ow_->StartObject("")
+ ->StartList("map_input")
+ ->RenderString("a", "b")
+ ->EndList()
+ ->EndObject();
+ CheckOutput(mm);
+}
+
+class ProtoStreamObjectWriterAnyTest : public BaseProtoStreamObjectWriterTest {
+ protected:
+ ProtoStreamObjectWriterAnyTest() {
+ vector<const Descriptor*> descriptors;
+ descriptors.push_back(AnyOut::descriptor());
+ descriptors.push_back(google::protobuf::DoubleValue::descriptor());
+ descriptors.push_back(google::protobuf::Any::descriptor());
+ ResetTypeInfo(descriptors);
+ }
+};
+
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyRenderSuccess) {
+ AnyOut any;
+ google::protobuf::Any* any_type = any.mutable_any();
+ any_type->set_type_url("type.googleapis.com/google.protobuf.DoubleValue");
+ google::protobuf::DoubleValue d;
+ d.set_value(40.2);
+ any_type->set_value(d.SerializeAsString());
+
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.DoubleValue")
+ ->RenderDouble("value", 40.2)
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(any);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, RecursiveAny) {
+ AnyOut out;
+ ::google::protobuf::Any* any = out.mutable_any();
+ any->set_type_url("type.googleapis.com/google.protobuf.Any");
+
+ ::google::protobuf::Any nested_any;
+ nested_any.set_type_url(
+ "type.googleapis.com/google.protobuf.testing.anys.AnyM");
+
+ AnyM m;
+ m.set_foo("foovalue");
+ nested_any.set_value(m.SerializeAsString());
+
+ any->set_value(nested_any.SerializeAsString());
+
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
+ ->StartObject("value")
+ ->RenderString("@type",
+ "type.googleapis.com/google.protobuf.testing.anys.AnyM")
+ ->RenderString("foo", "foovalue")
+ ->EndObject()
+ ->EndObject()
+ ->EndObject();
+
+ CheckOutput(out, 115);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, DoubleRecursiveAny) {
+ AnyOut out;
+ ::google::protobuf::Any* any = out.mutable_any();
+ any->set_type_url("type.googleapis.com/google.protobuf.Any");
+
+ ::google::protobuf::Any nested_any;
+ nested_any.set_type_url("type.googleapis.com/google.protobuf.Any");
+
+ ::google::protobuf::Any second_nested_any;
+ second_nested_any.set_type_url(
+ "type.googleapis.com/google.protobuf.testing.anys.AnyM");
+
+ AnyM m;
+ m.set_foo("foovalue");
+ second_nested_any.set_value(m.SerializeAsString());
+
+ nested_any.set_value(second_nested_any.SerializeAsString());
+ any->set_value(nested_any.SerializeAsString());
+
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
+ ->StartObject("value")
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
+ ->StartObject("value")
+ ->RenderString("@type",
+ "type.googleapis.com/google.protobuf.testing.anys.AnyM")
+ ->RenderString("foo", "foovalue")
+ ->EndObject()
+ ->EndObject()
+ ->EndObject()
+ ->EndObject();
+
+ CheckOutput(out, 159);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, EmptyAnyFromEmptyObject) {
+ AnyOut out;
+ out.mutable_any();
+
+ ow_->StartObject("")->StartObject("any")->EndObject()->EndObject();
+
+ CheckOutput(out, 2);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) {
+ AnyOut any;
+
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("Any"),
+ StringPiece(
+ "Missing or invalid @type for any field in "
+ "google.protobuf.testing.anys.AnyOut")));
+
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->StartObject("another")
+ ->EndObject()
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(any);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) {
+ AnyOut any;
+
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("Any"),
+ StringPiece(
+ "Missing or invalid @type for any field in "
+ "google.protobuf.testing.anys.AnyOut")));
+
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->StartList("another")
+ ->EndObject()
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(any);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails3) {
+ AnyOut any;
+
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("Any"),
+ StringPiece(
+ "Missing or invalid @type for any field in "
+ "google.protobuf.testing.anys.AnyOut")));
+
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->RenderString("value", "somevalue")
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(any);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithInvalidTypeUrlFails) {
+ AnyOut any;
+
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_, StringPiece("Any"),
+ StringPiece(
+ "Invalid type URL, type URLs must be of the form "
+ "'type.googleapis.com/<typename>', got: "
+ "type.other.com/some.Type")));
+
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "type.other.com/some.Type")
+ ->RenderDouble("value", 40.2)
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(any);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithUnknownTypeFails) {
+ AnyOut any;
+
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_, StringPiece("Any"),
+ StringPiece("Invalid type URL, unknown type: some.Type")));
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "type.googleapis.com/some.Type")
+ ->RenderDouble("value", 40.2)
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(any);
+}
+
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyNullInputFails) {
+ AnyOut any;
+
+ ow_->StartObject("")->RenderNull("any")->EndObject();
+ CheckOutput(any);
+}
+
+class ProtoStreamObjectWriterFieldMaskTest
+ : public BaseProtoStreamObjectWriterTest {
+ protected:
+ ProtoStreamObjectWriterFieldMaskTest() {
+ vector<const Descriptor*> descriptors;
+ descriptors.push_back(FieldMaskTest::descriptor());
+ descriptors.push_back(google::protobuf::FieldMask::descriptor());
+ ResetTypeInfo(descriptors);
+ }
+};
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, SimpleFieldMaskTest) {
+ FieldMaskTest expected;
+ expected.set_id("1");
+ expected.mutable_single_mask()->add_paths("path1");
+
+ ow_->StartObject("");
+ ow_->RenderString("id", "1");
+ ow_->RenderString("single_mask", "path1");
+ ow_->EndObject();
+
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, MutipleMasksInCompactForm) {
+ FieldMaskTest expected;
+ expected.set_id("1");
+ expected.mutable_single_mask()->add_paths("camel_case1");
+ expected.mutable_single_mask()->add_paths("camel_case2");
+ expected.mutable_single_mask()->add_paths("camel_case3");
+
+ ow_->StartObject("");
+ ow_->RenderString("id", "1");
+ ow_->RenderString("single_mask", "camelCase1,camelCase2,camelCase3");
+ ow_->EndObject();
+
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, RepeatedFieldMaskTest) {
+ FieldMaskTest expected;
+ expected.set_id("1");
+ google::protobuf::FieldMask* mask = expected.add_repeated_mask();
+ mask->add_paths("field1");
+ mask->add_paths("field2");
+ expected.add_repeated_mask()->add_paths("field3");
+
+ ow_->StartObject("");
+ ow_->RenderString("id", "1");
+ ow_->StartList("repeated_mask");
+ ow_->RenderString("", "field1,field2");
+ ow_->RenderString("", "field3");
+ ow_->EndList();
+ ow_->EndObject();
+
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, EmptyFieldMaskTest) {
+ FieldMaskTest expected;
+ expected.set_id("1");
+
+ ow_->StartObject("");
+ ow_->RenderString("id", "1");
+ ow_->RenderString("single_mask", "");
+ ow_->EndObject();
+
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, MaskUsingApiaryStyleShouldWork) {
+ FieldMaskTest expected;
+ expected.set_id("1");
+
+ ow_->StartObject("");
+ ow_->RenderString("id", "1");
+ // Case1
+ ow_->RenderString("single_mask",
+ "outerField(camelCase1,camelCase2,camelCase3)");
+ expected.mutable_single_mask()->add_paths("outer_field.camel_case1");
+ expected.mutable_single_mask()->add_paths("outer_field.camel_case2");
+ expected.mutable_single_mask()->add_paths("outer_field.camel_case3");
+
+ ow_->StartList("repeated_mask");
+
+ ow_->RenderString("", "a(field1,field2)");
+ google::protobuf::FieldMask* mask = expected.add_repeated_mask();
+ mask->add_paths("a.field1");
+ mask->add_paths("a.field2");
+
+ ow_->RenderString("", "a(field3)");
+ mask = expected.add_repeated_mask();
+ mask->add_paths("a.field3");
+
+ ow_->RenderString("", "a()");
+ expected.add_repeated_mask();
+
+ ow_->RenderString("", "a(,)");
+ expected.add_repeated_mask();
+
+ ow_->RenderString("", "a(field1(field2(field3)))");
+ mask = expected.add_repeated_mask();
+ mask->add_paths("a.field1.field2.field3");
+
+ ow_->RenderString("", "a(field1(field2(field3,field4),field5),field6)");
+ mask = expected.add_repeated_mask();
+ mask->add_paths("a.field1.field2.field3");
+ mask->add_paths("a.field1.field2.field4");
+ mask->add_paths("a.field1.field5");
+ mask->add_paths("a.field6");
+
+ ow_->RenderString("", "a(id,field1(id,field2(field3,field4),field5),field6)");
+ mask = expected.add_repeated_mask();
+ mask->add_paths("a.id");
+ mask->add_paths("a.field1.id");
+ mask->add_paths("a.field1.field2.field3");
+ mask->add_paths("a.field1.field2.field4");
+ mask->add_paths("a.field1.field5");
+ mask->add_paths("a.field6");
+
+ ow_->RenderString("", "a(((field3,field4)))");
+ mask = expected.add_repeated_mask();
+ mask->add_paths("a.field3");
+ mask->add_paths("a.field4");
+
+ ow_->EndList();
+ ow_->EndObject();
+
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreCloseThanOpenParentheses) {
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
+ StringPiece(
+ "Field 'single_mask', Invalid FieldMask 'a(b,c))'. "
+ "Cannot find matching '(' for all ')'.")));
+
+ ow_->StartObject("");
+ ow_->RenderString("id", "1");
+ ow_->RenderString("single_mask", "a(b,c))");
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreOpenThanCloseParentheses) {
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
+ StringPiece(
+ "Field 'single_mask', Invalid FieldMask 'a(((b,c)'. Cannot "
+ "find matching ')' for all '('.")));
+
+ ow_->StartObject("");
+ ow_->RenderString("id", "1");
+ ow_->RenderString("single_mask", "a(((b,c)");
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, PathWithMapKeyShouldWork) {
+ FieldMaskTest expected;
+ expected.mutable_single_mask()->add_paths("path.to.map[\"key1\"]");
+ expected.mutable_single_mask()->add_paths(
+ "path.to.map[\"e\\\"[]][scape\\\"\"]");
+ expected.mutable_single_mask()->add_paths("path.to.map[\"key2\"]");
+
+ ow_->StartObject("");
+ ow_->RenderString("single_mask",
+ "path.to.map[\"key1\"],path.to.map[\"e\\\"[]][scape\\\"\"],"
+ "path.to.map[\"key2\"]");
+ ow_->EndObject();
+
+ CheckOutput(expected);
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest,
+ MapKeyMustBeAtTheEndOfAPathSegment) {
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
+ StringPiece(
+ "Field 'single_mask', Invalid FieldMask "
+ "'path.to.map[\"key1\"]a,path.to.map[\"key2\"]'. "
+ "Map keys should be at the end of a path segment.")));
+
+ ow_->StartObject("");
+ ow_->RenderString("single_mask",
+ "path.to.map[\"key1\"]a,path.to.map[\"key2\"]");
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustEnd) {
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
+ StringPiece(
+ "Field 'single_mask', Invalid FieldMask "
+ "'path.to.map[\"key1\"'. Map keys should be "
+ "represented as [\"some_key\"].")));
+
+ ow_->StartObject("");
+ ow_->RenderString("single_mask", "path.to.map[\"key1\"");
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustBeEscapedCorrectly) {
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
+ StringPiece(
+ "Field 'single_mask', Invalid FieldMask "
+ "'path.to.map[\"ke\"y1\"]'. Map keys should be "
+ "represented as [\"some_key\"].")));
+
+ ow_->StartObject("");
+ ow_->RenderString("single_mask", "path.to.map[\"ke\"y1\"]");
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyCanContainAnyChars) {
+ FieldMaskTest expected;
+ expected.mutable_single_mask()->add_paths(
+ "path.to.map[\"(),[],\\\"'!@#$%^&*123_|War孙天涌,./?><\\\\\"]");
+ expected.mutable_single_mask()->add_paths("path.to.map[\"key2\"]");
+
+ ow_->StartObject("");
+ ow_->RenderString(
+ "single_mask",
+ "path.to.map[\"(),[],\\\"'!@#$%^&*123_|War孙天涌,./?><\\\\\"],"
+ "path.to.map[\"key2\"]");
+ ow_->EndObject();
+
+ CheckOutput(expected);
+}
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/snake2camel_objectwriter.h b/src/google/protobuf/util/internal/snake2camel_objectwriter.h
new file mode 100644
index 00000000..1a32bc56
--- /dev/null
+++ b/src/google/protobuf/util/internal/snake2camel_objectwriter.h
@@ -0,0 +1,187 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_SNAKE2CAMEL_OBJECTWRITER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_SNAKE2CAMEL_OBJECTWRITER_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/util/internal/object_writer.h>
+#include <google/protobuf/util/internal/utility.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// Snake2CamelObjectWriter is an ObjectWriter than translates each field name
+// from snake_case to camelCase. Typical usage is:
+// ProtoStreamObjectSource psos(...);
+// JsonObjectWriter jow(...);
+// Snake2CamelObjectWriter snake_to_camel(&jow);
+// psos.writeTo(&snake_to_camel);
+class Snake2CamelObjectWriter : public ObjectWriter {
+ public:
+ explicit Snake2CamelObjectWriter(ObjectWriter* ow)
+ : ow_(ow), normalize_case_(true) {}
+ virtual ~Snake2CamelObjectWriter() {}
+
+ // ObjectWriter methods.
+ virtual Snake2CamelObjectWriter* StartObject(StringPiece name) {
+ ow_->StartObject(ShouldNormalizeCase(name)
+ ? StringPiece(StringPiece(ToCamelCase(name)))
+ : name);
+ return this;
+ }
+
+ virtual Snake2CamelObjectWriter* EndObject() {
+ ow_->EndObject();
+ return this;
+ }
+
+ virtual Snake2CamelObjectWriter* StartList(StringPiece name) {
+ ow_->StartList(ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name))
+ : name);
+ return this;
+ }
+
+ virtual Snake2CamelObjectWriter* EndList() {
+ ow_->EndList();
+ return this;
+ }
+
+ virtual Snake2CamelObjectWriter* RenderBool(StringPiece name, bool value) {
+ ow_->RenderBool(
+ ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
+ value);
+ return this;
+ }
+
+ virtual Snake2CamelObjectWriter* RenderInt32(StringPiece name, int32 value) {
+ ow_->RenderInt32(
+ ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
+ value);
+ return this;
+ }
+
+ virtual Snake2CamelObjectWriter* RenderUint32(StringPiece name,
+ uint32 value) {
+ ow_->RenderUint32(
+ ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
+ value);
+ return this;
+ }
+
+ virtual Snake2CamelObjectWriter* RenderInt64(StringPiece name, int64 value) {
+ ow_->RenderInt64(
+ ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
+ value);
+ return this;
+ }
+
+ virtual Snake2CamelObjectWriter* RenderUint64(StringPiece name,
+ uint64 value) {
+ ow_->RenderUint64(
+ ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
+ value);
+ return this;
+ }
+
+ virtual Snake2CamelObjectWriter* RenderDouble(StringPiece name,
+ double value) {
+ ow_->RenderDouble(
+ ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
+ value);
+ return this;
+ }
+
+ virtual Snake2CamelObjectWriter* RenderFloat(StringPiece name, float value) {
+ ow_->RenderFloat(
+ ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
+ value);
+ return this;
+ }
+
+ virtual Snake2CamelObjectWriter* RenderString(StringPiece name,
+ StringPiece value) {
+ ow_->RenderString(
+ ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
+ value);
+ return this;
+ }
+
+ virtual Snake2CamelObjectWriter* RenderBytes(StringPiece name,
+ StringPiece value) {
+ ow_->RenderBytes(
+ ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
+ value);
+ return this;
+ }
+
+ virtual Snake2CamelObjectWriter* RenderNull(StringPiece name) {
+ ow_->RenderNull(ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name))
+ : name);
+ return this;
+ }
+
+ virtual Snake2CamelObjectWriter* DisableCaseNormalizationForNextKey() {
+ normalize_case_ = false;
+ return this;
+ }
+
+ private:
+ ObjectWriter* ow_;
+ bool normalize_case_;
+
+ bool ShouldNormalizeCase(StringPiece name) {
+ if (normalize_case_) {
+ return !IsCamel(name);
+ } else {
+ normalize_case_ = true;
+ return false;
+ }
+ }
+
+ bool IsCamel(StringPiece name) {
+ return name.empty() || (ascii_islower(name[0]) && !name.contains("_"));
+ }
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Snake2CamelObjectWriter);
+};
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_SNAKE2CAMEL_OBJECTWRITER_H__
diff --git a/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc b/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc
new file mode 100644
index 00000000..67388c3b
--- /dev/null
+++ b/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc
@@ -0,0 +1,311 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/snake2camel_objectwriter.h>
+#include <google/protobuf/util/internal/expecting_objectwriter.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+class Snake2CamelObjectWriterTest : public ::testing::Test {
+ protected:
+ Snake2CamelObjectWriterTest() : mock_(), expects_(&mock_), testing_(&mock_) {}
+ virtual ~Snake2CamelObjectWriterTest() {}
+
+ MockObjectWriter mock_;
+ ExpectingObjectWriter expects_;
+ Snake2CamelObjectWriter testing_;
+};
+
+TEST_F(Snake2CamelObjectWriterTest, Empty) {
+ // Set expectation
+ expects_.StartObject("")->EndObject();
+
+ // Actual testing
+ testing_.StartObject("")->EndObject();
+}
+
+TEST_F(Snake2CamelObjectWriterTest, UnderscoresOnly) {
+ // Set expectation
+ expects_.StartObject("")
+ ->RenderInt32("", 1)
+ ->RenderInt32("", 2)
+ ->RenderInt32("", 3)
+ ->RenderInt32("", 4)
+ ->RenderInt32("", 5)
+ ->EndObject();
+
+ // Actual testing
+ testing_.StartObject("")
+ ->RenderInt32("_", 1)
+ ->RenderInt32("__", 2)
+ ->RenderInt32("___", 3)
+ ->RenderInt32("____", 4)
+ ->RenderInt32("_____", 5)
+ ->EndObject();
+}
+
+TEST_F(Snake2CamelObjectWriterTest, LowercaseOnly) {
+ // Set expectation
+ expects_.StartObject("")
+ ->RenderString("key", "value")
+ ->RenderString("abracadabra", "magic")
+ ->EndObject();
+
+ // Actual testing
+ testing_.StartObject("")
+ ->RenderString("key", "value")
+ ->RenderString("abracadabra", "magic")
+ ->EndObject();
+}
+
+TEST_F(Snake2CamelObjectWriterTest, UppercaseOnly) {
+ // Set expectation
+ expects_.StartObject("")
+ ->RenderString("key", "VALUE")
+ ->RenderString("abracadabra", "MAGIC")
+ ->EndObject();
+
+ // Actual testing
+ testing_.StartObject("")
+ ->RenderString("KEY", "VALUE")
+ ->RenderString("ABRACADABRA", "MAGIC")
+ ->EndObject();
+}
+
+TEST_F(Snake2CamelObjectWriterTest, CamelCase) {
+ // Set expectation
+ expects_.StartObject("")
+ ->RenderString("camelCase", "camelCase")
+ ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog",
+ "theQuickBrownFoxJumpsOverTheLazyDog")
+ ->EndObject();
+
+ // Actual testing
+ testing_.StartObject("")
+ ->RenderString("camelCase", "camelCase")
+ ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog",
+ "theQuickBrownFoxJumpsOverTheLazyDog")
+ ->EndObject();
+}
+
+TEST_F(Snake2CamelObjectWriterTest, FirstCapCamelCase) {
+ // Sets expectation
+ expects_.StartObject("camel")
+ ->RenderString("camelCase", "CamelCase")
+ ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog",
+ "TheQuickBrownFoxJumpsOverTheLazyDog")
+ ->EndObject();
+
+ // Actual testing
+ testing_.StartObject("Camel")
+ ->RenderString("CamelCase", "CamelCase")
+ ->RenderString("TheQuickBrownFoxJumpsOverTheLazyDog",
+ "TheQuickBrownFoxJumpsOverTheLazyDog")
+ ->EndObject();
+}
+
+TEST_F(Snake2CamelObjectWriterTest, LastCapCamelCase) {
+ // Sets expectation
+ expects_.StartObject("lastCapCamelCasE")->EndObject();
+
+ // Actual testing
+ testing_.StartObject("lastCapCamelCasE")->EndObject();
+}
+
+TEST_F(Snake2CamelObjectWriterTest, MixedCapCamelCase) {
+ // Sets expectation
+ expects_.StartObject("googleIsTheBest")
+ ->RenderFloat("iLoveGOOGLE", 1.61803f)
+ ->RenderFloat("goGoogleGO", 2.71828f)
+ ->RenderFloat("gBikeISCool", 3.14159f)
+ ->EndObject();
+
+ // Actual testing
+ testing_.StartObject("GOOGLEIsTheBest")
+ ->RenderFloat("ILoveGOOGLE", 1.61803f)
+ ->RenderFloat("GOGoogleGO", 2.71828f)
+ ->RenderFloat("GBikeISCool", 3.14159f)
+ ->EndObject();
+}
+
+TEST_F(Snake2CamelObjectWriterTest, MixedCase) {
+ // Sets expectation
+ expects_.StartObject("snakeCaseCamelCase")
+ ->RenderBool("camelCaseSnakeCase", false)
+ ->RenderBool("mixedCamelAndUnderScores", false)
+ ->RenderBool("goGOOGLEGo", true)
+ ->EndObject();
+
+ // Actual testing
+ testing_.StartObject("snake_case_camelCase")
+ ->RenderBool("camelCase_snake_case", false)
+ ->RenderBool("MixedCamel_And_UnderScores", false)
+ ->RenderBool("Go_GOOGLEGo", true)
+ ->EndObject();
+}
+
+TEST_F(Snake2CamelObjectWriterTest, SnakeCase) {
+ // Sets expectation
+ expects_.StartObject("")
+ ->RenderString("snakeCase", "snake_case")
+ ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog",
+ "the_quick_brown_fox_jumps_over_the_lazy_dog")
+ ->EndObject();
+
+ // Actual testing
+ testing_.StartObject("")
+ ->RenderString("snake_case", "snake_case")
+ ->RenderString("the_quick_brown_fox_jumps_over_the_lazy_dog",
+ "the_quick_brown_fox_jumps_over_the_lazy_dog")
+ ->EndObject();
+}
+
+TEST_F(Snake2CamelObjectWriterTest, FirstCapSnakeCase) {
+ // Sets expectation
+ expects_.StartObject("firstCapSnakeCase")
+ ->RenderBool("helloWorld", true)
+ ->EndObject();
+
+ // Actual testing
+ testing_.StartObject("First_Cap_Snake_Case")
+ ->RenderBool("Hello_World", true)
+ ->EndObject();
+}
+
+TEST_F(Snake2CamelObjectWriterTest, AllCapSnakeCase) {
+ // Sets expectation
+ expects_.StartObject("allCAPSNAKECASE")
+ ->RenderDouble("nyseGOOGL", 600.0L)
+ ->RenderDouble("aBCDE", 1.0L)
+ ->RenderDouble("klMNOP", 2.0L)
+ ->RenderDouble("abcIJKPQRXYZ", 3.0L)
+ ->EndObject();
+
+ // Actual testing
+ testing_.StartObject("ALL_CAP_SNAKE_CASE")
+ ->RenderDouble("NYSE_GOOGL", 600.0L)
+ ->RenderDouble("A_B_C_D_E", 1.0L)
+ ->RenderDouble("KL_MN_OP", 2.0L)
+ ->RenderDouble("ABC_IJK_PQR_XYZ", 3.0L)
+ ->EndObject();
+}
+
+TEST_F(Snake2CamelObjectWriterTest, RepeatedUnderScoreSnakeCase) {
+ // Sets expectation
+ expects_.StartObject("")
+ ->RenderInt32("doubleUnderscoreSnakeCase", 2)
+ ->RenderInt32("tripleUnderscoreFirstCap", 3)
+ ->RenderInt32("quadrupleUNDERSCOREALLCAP", 4)
+ ->EndObject();
+
+ // Actual testing
+ testing_.StartObject("")
+ ->RenderInt32("double__underscore__snake__case", 2)
+ ->RenderInt32("Triple___Underscore___First___Cap", 3)
+ ->RenderInt32("QUADRUPLE____UNDERSCORE____ALL____CAP", 4)
+ ->EndObject();
+}
+
+TEST_F(Snake2CamelObjectWriterTest, LeadingUnderscoreSnakeCase) {
+ // Sets expectation
+ expects_.StartObject("leadingUnderscoreSnakeCase")
+ ->RenderUint32("leadingDoubleUnderscore", 2)
+ ->RenderUint32("leadingTripleUnderscoreFirstCap", 3)
+ ->RenderUint32("leadingQUADRUPLEUNDERSCOREALLCAP", 4)
+ ->EndObject();
+
+ // Actual testing
+ testing_.StartObject("_leading_underscore_snake_case")
+ ->RenderUint32("__leading_double_underscore", 2)
+ ->RenderUint32("___Leading_Triple_Underscore_First_Cap", 3)
+ ->RenderUint32("____LEADING_QUADRUPLE_UNDERSCORE_ALL_CAP", 4)
+ ->EndObject();
+}
+
+TEST_F(Snake2CamelObjectWriterTest, TrailingUnderscoreSnakeCase) {
+ // Sets expectation
+ expects_.StartObject("trailingUnderscoreSnakeCase")
+ ->RenderInt64("trailingDoubleUnderscore", 2L)
+ ->RenderInt64("trailingTripleUnderscoreFirstCap", 3L)
+ ->RenderInt64("trailingQUADRUPLEUNDERSCOREALLCAP", 4L)
+ ->EndObject();
+
+ // Actual testing
+ testing_.StartObject("trailing_underscore_snake_case")
+ ->RenderInt64("trailing_double_underscore__", 2L)
+ ->RenderInt64("Trailing_Triple_Underscore_First_Cap___", 3L)
+ ->RenderInt64("TRAILING_QUADRUPLE_UNDERSCORE_ALL_CAP____", 4L)
+ ->EndObject();
+}
+
+TEST_F(Snake2CamelObjectWriterTest, EnclosingUnderscoreSnakeCase) {
+ // Sets expectation
+ expects_.StartObject("enclosingUnderscoreSnakeCase")
+ ->RenderUint64("enclosingDoubleUnderscore", 2L)
+ ->RenderUint64("enclosingTripleUnderscoreFirstCap", 3L)
+ ->RenderUint64("enclosingQUADRUPLEUNDERSCOREALLCAP", 4L)
+ ->EndObject();
+
+ // Actual testing
+ testing_.StartObject("_enclosing_underscore_snake_case_")
+ ->RenderUint64("__enclosing_double_underscore__", 2L)
+ ->RenderUint64("___Enclosing_Triple_Underscore_First_Cap___", 3L)
+ ->RenderUint64("____ENCLOSING_QUADRUPLE_UNDERSCORE_ALL_CAP____", 4L)
+ ->EndObject();
+}
+
+TEST_F(Snake2CamelObjectWriterTest, DisableCaseNormalizationOnlyDisablesFirst) {
+ // Sets expectation
+ expects_.StartObject("")
+ ->RenderString("snakeCase", "snake_case")
+ ->RenderString(
+ "the_quick_brown_fox_jumps_over_the_lazy_dog", // case retained
+ "the_quick_brown_fox_jumps_over_the_lazy_dog")
+ ->RenderBool("theSlowFox", true) // disable case not in effect
+ ->EndObject();
+
+ // Actual testing
+ testing_.StartObject("")
+ ->RenderString("snake_case", "snake_case")
+ ->DisableCaseNormalizationForNextKey()
+ ->RenderString("the_quick_brown_fox_jumps_over_the_lazy_dog",
+ "the_quick_brown_fox_jumps_over_the_lazy_dog")
+ ->RenderBool("the_slow_fox", true)
+ ->EndObject();
+}
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/structured_objectwriter.h b/src/google/protobuf/util/internal/structured_objectwriter.h
new file mode 100644
index 00000000..3f065d6b
--- /dev/null
+++ b/src/google/protobuf/util/internal/structured_objectwriter.h
@@ -0,0 +1,118 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_STRUCTURED_OBJECTWRITER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_STRUCTURED_OBJECTWRITER_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/util/internal/object_writer.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+// An StructuredObjectWriter is an ObjectWriter for writing
+// tree-structured data in a stream of events representing objects
+// and collections. Implementation of this interface can be used to
+// write an object stream to an in-memory structure, protobufs,
+// JSON, XML, or any other output format desired. The ObjectSource
+// interface is typically used as the source of an object stream.
+//
+// See JsonObjectWriter for a sample implementation of
+// StructuredObjectWriter and its use.
+//
+// Derived classes could be thread-unsafe.
+class LIBPROTOBUF_EXPORT StructuredObjectWriter : public ObjectWriter {
+ public:
+ virtual ~StructuredObjectWriter() {}
+
+ protected:
+ // A base element class for subclasses to extend, makes tracking state easier.
+ //
+ // StructuredObjectWriter behaves as a visitor. BaseElement represents a node
+ // in the input tree. Implementation of StructuredObjectWriter should also
+ // extend BaseElement to keep track of the location in the input tree.
+ class LIBPROTOBUF_EXPORT BaseElement {
+ public:
+ // Takes ownership of the parent Element.
+ explicit BaseElement(BaseElement* parent)
+ : parent_(parent), level_(parent == NULL ? 0 : parent->level() + 1) {}
+ virtual ~BaseElement() {}
+
+ // Releases ownership of the parent and returns a pointer to it.
+ template <typename ElementType>
+ ElementType* pop() {
+ return down_cast<ElementType*>(parent_.release());
+ }
+
+ // Returns true if this element is the root.
+ bool is_root() const { return parent_ == NULL; }
+
+ // Returns the number of hops from this element to the root element.
+ int level() const { return level_; }
+
+ protected:
+ // Returns pointer to parent element without releasing ownership.
+ virtual BaseElement* parent() const { return parent_.get(); }
+
+ private:
+ // Pointer to the parent Element.
+ google::protobuf::scoped_ptr<BaseElement> parent_;
+
+ // Number of hops to the root Element.
+ // The root Element has NULL parent_ and a level_ of 0.
+ const int level_;
+
+ GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseElement);
+ };
+
+ StructuredObjectWriter() {}
+
+ // Returns the current element. Used for indentation and name overrides.
+ virtual BaseElement* element() = 0;
+
+ private:
+ // Do not add any data members to this class.
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StructuredObjectWriter);
+};
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_STRUCTURED_OBJECTWRITER_H__
diff --git a/src/google/protobuf/util/internal/testdata/anys.proto b/src/google/protobuf/util/internal/testdata/anys.proto
new file mode 100644
index 00000000..18c59cbb
--- /dev/null
+++ b/src/google/protobuf/util/internal/testdata/anys.proto
@@ -0,0 +1,53 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Proto to test Proto3 Any serialization.
+syntax = "proto3";
+
+package google.protobuf.testing.anys;
+option java_package = "com.google.protobuf.testing.anys";
+
+import "google/protobuf/any.proto";
+
+message AnyIn {
+ string something = 1;
+}
+
+message AnyOut {
+ google.protobuf.Any any = 1;
+}
+
+message AnyM {
+ string foo = 1;
+}
+
+service TestService {
+ rpc Call(AnyIn) returns (AnyOut);
+}
diff --git a/src/google/protobuf/util/internal/testdata/books.proto b/src/google/protobuf/util/internal/testdata/books.proto
new file mode 100644
index 00000000..6e2f109b
--- /dev/null
+++ b/src/google/protobuf/util/internal/testdata/books.proto
@@ -0,0 +1,171 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: sven@google.com (Sven Mawson)
+//
+// Sample protos for testing.
+syntax = "proto2";
+
+package google.protobuf.testing;
+
+// A book
+message Book {
+ optional string title = 1;
+ optional Author author = 2;
+ optional uint32 length = 3;
+ optional int64 published = 4;
+ optional bytes content = 5;
+
+ optional group Data = 6 {
+ optional uint32 year = 7;
+ optional string copyright = 8;
+ }
+
+ message Label {
+ optional string key = 1;
+ optional string value = 2;
+ }
+
+ optional Publisher publisher = 9;
+ repeated Label labels = 10;
+
+ extensions 200 to 499;
+}
+
+// A publisher of a book, tests required fields.
+message Publisher {
+ required string name = 1;
+}
+
+// An author of a book
+message Author {
+ optional uint64 id = 1;
+ optional string name = 2;
+ repeated string pseudonym = 3;
+ optional bool alive = 4;
+ repeated Author friend = 5;
+}
+
+// For testing resiliency of our protostream parser.
+// Field numbers of Author are reused for something else.
+message BadAuthor {
+ optional string id = 1; // non-length-delimited to length-delimited.
+ repeated uint64 name = 2; // string to repeated (both length-delimited).
+ optional string pseudonym = 3; // Repeated to optional.
+ repeated bool alive = 4 [packed=true]; // Optional to repeated.
+}
+
+// All primitive types
+message Primitive {
+ // 32 bit numbers:
+ optional fixed32 fix32 = 1;
+ optional uint32 u32 = 2;
+ optional int32 i32 = 3;
+ optional sfixed32 sf32 = 4;
+ optional sint32 s32 = 5;
+
+ // 64 bit numbers:
+ optional fixed64 fix64 = 6;
+ optional uint64 u64 = 7;
+ optional int64 i64 = 8;
+ optional sfixed64 sf64 = 9;
+ optional sint64 s64 = 10;
+
+ // The other stuff.
+ optional string str = 11;
+ optional bytes bytes = 12;
+ optional float float = 13;
+ optional double double = 14;
+ optional bool bool = 15;
+
+ // repeated 32 bit numbers:
+ repeated fixed32 rep_fix32 = 16;
+ repeated uint32 rep_u32 = 17;
+ repeated int32 rep_i32 = 18;
+ repeated sfixed32 rep_sf32 = 19;
+ repeated sint32 rep_s32 = 20;
+
+ // repeated 64 bit numbers:
+ repeated fixed64 rep_fix64 = 21;
+ repeated uint64 rep_u64 = 22;
+ repeated int64 rep_i64 = 23;
+ repeated sfixed64 rep_sf64 = 24;
+ repeated sint64 rep_s64 = 25;
+
+ // repeated other stuff:
+ repeated string rep_str = 26;
+ repeated bytes rep_bytes = 27;
+ repeated float rep_float = 28;
+ repeated double rep_double = 29;
+ repeated bool rep_bool = 30;
+}
+
+// Test packed versions of all repeated primitives.
+// The field numbers should match their non-packed version in Primitive message.
+message PackedPrimitive {
+ // repeated 32 bit numbers:
+ repeated fixed32 rep_fix32 = 16 [packed=true];
+ repeated uint32 rep_u32 = 17 [packed=true];
+ repeated int32 rep_i32 = 18 [packed=true];
+ repeated sfixed32 rep_sf32 = 19 [packed=true];
+ repeated sint32 rep_s32 = 20 [packed=true];
+
+ // repeated 64 bit numbers:
+ repeated fixed64 rep_fix64 = 21 [packed=true];
+ repeated uint64 rep_u64 = 22 [packed=true];
+ repeated int64 rep_i64 = 23 [packed=true];
+ repeated sfixed64 rep_sf64 = 24 [packed=true];
+ repeated sint64 rep_s64 = 25 [packed=true];
+
+ // repeated other stuff:
+ repeated float rep_float = 28 [packed=true];
+ repeated double rep_double = 29 [packed=true];
+ repeated bool rep_bool = 30 [packed=true];
+}
+
+// Test extensions.
+extend Book {
+ repeated Author more_author = 201;
+}
+
+// Test nested extensions.
+message NestedBook {
+ extend Book {
+ optional NestedBook another_book = 301;
+ }
+ // Recurse
+ optional Book book = 1;
+}
+
+// For testing resiliency of our protostream parser.
+// Field number of NestedBook is reused for something else.
+message BadNestedBook {
+ repeated uint32 book = 1 [packed=true]; // Packed to optional message.
+}
diff --git a/src/google/protobuf/util/internal/testdata/default_value.proto b/src/google/protobuf/util/internal/testdata/default_value.proto
new file mode 100644
index 00000000..ecfc8119
--- /dev/null
+++ b/src/google/protobuf/util/internal/testdata/default_value.proto
@@ -0,0 +1,162 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf.testing;
+
+import "google/protobuf/any.proto";
+import "google/protobuf/struct.proto";
+import "google/protobuf/wrappers.proto";
+
+message DefaultValueTestCases {
+ DoubleMessage empty_double = 1;
+ DoubleMessage double_with_default_value = 2;
+ DoubleMessage double_with_nondefault_value = 3;
+ DoubleMessage repeated_double = 4;
+ DoubleMessage nested_message = 5;
+ DoubleMessage repeated_nested_message = 6;
+ StructMessage empty_struct = 201;
+ StructMessage empty_struct2 = 202;
+ StructMessage struct_with_null_value = 203;
+ StructMessage struct_with_values = 204;
+ StructMessage struct_with_nested_struct = 205;
+ StructMessage struct_with_nested_list = 206;
+ StructMessage struct_with_list_of_nulls = 207;
+ StructMessage struct_with_list_of_lists = 208;
+ StructMessage struct_with_list_of_structs = 209;
+ google.protobuf.Struct top_level_struct = 210;
+ ValueMessage value_wrapper_simple = 212;
+ ValueMessage value_wrapper_with_struct = 213;
+ ValueMessage value_wrapper_with_list = 214;
+ ListValueMessage list_value_wrapper = 215;
+ google.protobuf.Value top_level_value_simple = 216;
+ google.protobuf.Value top_level_value_with_struct = 217;
+ google.protobuf.Value top_level_value_with_list = 218;
+ google.protobuf.ListValue top_level_listvalue = 219;
+ AnyMessage empty_any = 301;
+ AnyMessage type_only_any = 302;
+ AnyMessage recursive_any = 303;
+ AnyMessage any_with_message_value = 304;
+ AnyMessage any_with_nested_message = 305;
+ AnyMessage any_with_message_containing_map = 306;
+ AnyMessage any_with_message_containing_struct = 307;
+ google.protobuf.Any top_level_any = 308;
+ StringtoIntMap empty_map = 401;
+ StringtoIntMap string_to_int = 402;
+ IntToStringMap int_to_string = 403;
+ MixedMap mixed1 = 404;
+ MixedMap2 mixed2 = 405;
+ MessageMap map_of_objects = 406;
+ DoubleValueMessage double_value = 501;
+ DoubleValueMessage double_value_default = 502;
+}
+
+message DoubleMessage {
+ double double_value = 1;
+ repeated double repeated_double = 2;
+ DoubleMessage nested_message = 3;
+ repeated DoubleMessage repeated_nested_message = 4;
+ google.protobuf.DoubleValue double_wrapper = 100;
+}
+
+message StructMessage {
+ google.protobuf.Struct struct = 1;
+}
+
+message ValueMessage {
+ google.protobuf.Value value = 1;
+}
+
+message ListValueMessage {
+ google.protobuf.ListValue shopping_list = 1;
+}
+message RequestMessage {
+ string content = 1;
+}
+
+// A test service.
+service DefaultValueTestService {
+ // A test method.
+ rpc Call(RequestMessage) returns (DefaultValueTestCases);
+}
+
+message AnyMessage {
+ google.protobuf.Any any = 1;
+ AnyData data = 2;
+}
+
+message AnyData {
+ int32 attr = 1;
+ string str = 2;
+ repeated string msgs = 3;
+ AnyData nested_data = 4;
+ map<string, string> map_data = 7;
+ google.protobuf.Struct struct_data = 8;
+ repeated AnyData repeated_data = 9;
+}
+
+message StringtoIntMap {
+ map<string, int32> map = 1;
+}
+
+message IntToStringMap {
+ map<int32, string> map = 1;
+}
+
+message MixedMap {
+ string msg = 1;
+ map<string, float> map = 2;
+ int32 int_value = 3;
+}
+
+message MixedMap2 {
+ enum E {
+ E0 = 0;
+ E1 = 1;
+ E2 = 2;
+ E3 = 3;
+ }
+ map<int32, bool> map = 1;
+ E ee = 2;
+ string msg = 4;
+}
+
+message MessageMap {
+ message M {
+ int32 inner_int = 1;
+ string inner_text = 2;
+ }
+ map<string, M> map = 1;
+}
+
+message DoubleValueMessage {
+ google.protobuf.DoubleValue double = 1;
+}
diff --git a/src/google/protobuf/util/internal/testdata/default_value_test.proto b/src/google/protobuf/util/internal/testdata/default_value_test.proto
new file mode 100644
index 00000000..21b85e6d
--- /dev/null
+++ b/src/google/protobuf/util/internal/testdata/default_value_test.proto
@@ -0,0 +1,46 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf.testing;
+
+message DefaultValueTest {
+ double double_value = 1;
+ repeated double repeated_double = 2;
+ float float_value = 3;
+ int64 int64_value = 5;
+ uint64 uint64_value = 7;
+ int32 int32_value = 9;
+ uint32 uint32_value = 11;
+ bool bool_value = 13;
+ string string_value = 15;
+ bytes bytes_value = 17 [ctype = CORD];
+}
diff --git a/src/google/protobuf/util/internal/testdata/field_mask.proto b/src/google/protobuf/util/internal/testdata/field_mask.proto
new file mode 100644
index 00000000..e8b2bc5f
--- /dev/null
+++ b/src/google/protobuf/util/internal/testdata/field_mask.proto
@@ -0,0 +1,71 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf.testing;
+
+import "google/protobuf/field_mask.proto";
+
+message NestedFieldMask {
+ string data = 1;
+ google.protobuf.FieldMask single_mask = 2;
+ repeated google.protobuf.FieldMask repeated_mask = 3;
+}
+
+message FieldMaskTest {
+ string id = 1;
+ google.protobuf.FieldMask single_mask = 2;
+ repeated google.protobuf.FieldMask repeated_mask = 3;
+ repeated NestedFieldMask nested_mask = 4;
+}
+
+message FieldMaskTestCases {
+ FieldMaskWrapper single_mask = 1;
+ FieldMaskWrapper multiple_mask = 2;
+ FieldMaskWrapper snake_camel = 3;
+ FieldMaskWrapper empty_field = 4;
+ FieldMaskWrapper apiary_format1 = 5;
+ FieldMaskWrapper apiary_format2 = 6;
+ FieldMaskWrapper apiary_format3 = 7;
+ FieldMaskWrapper map_key1 = 8;
+ FieldMaskWrapper map_key2 = 9;
+ FieldMaskWrapper map_key3 = 10;
+ FieldMaskWrapper map_key4 = 11;
+ FieldMaskWrapper map_key5 = 12;
+}
+
+message FieldMaskWrapper {
+ google.protobuf.FieldMask mask = 1;
+}
+
+service FieldMaskTestService {
+ rpc Call(FieldMaskTestCases) returns (FieldMaskTestCases);
+}
diff --git a/src/google/protobuf/util/internal/testdata/maps.proto b/src/google/protobuf/util/internal/testdata/maps.proto
new file mode 100644
index 00000000..7fb42a26
--- /dev/null
+++ b/src/google/protobuf/util/internal/testdata/maps.proto
@@ -0,0 +1,57 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Proto to test proto3 maps.
+syntax = "proto3";
+
+package google.protobuf.testing.maps;
+option java_package = "com.google.protobuf.testing.maps";
+
+message MapIn {
+ string other = 1;
+ repeated string things = 2;
+ map<string, string> map_input = 3;
+}
+
+message MapOut {
+ map<string, MapM> map1 = 1;
+ map<string, MapOut> map2 = 2;
+ map<int32, string> map3 = 3;
+ string bar = 4;
+}
+
+message MapM {
+ string foo = 1;
+}
+
+service TestService {
+ rpc Call1(MapIn) returns (MapOut);
+ rpc Call2(MapIn) returns (MapOut);
+}
diff --git a/src/google/protobuf/util/internal/testdata/struct.proto b/src/google/protobuf/util/internal/testdata/struct.proto
new file mode 100644
index 00000000..c15aba0d
--- /dev/null
+++ b/src/google/protobuf/util/internal/testdata/struct.proto
@@ -0,0 +1,45 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Proto to test proto3 struct.
+syntax = "proto3";
+
+package google.protobuf.testing.structs;
+option java_package = "com.google.protobuf.testing.structs";
+
+import "google/protobuf/struct.proto";
+
+message StructType {
+ google.protobuf.Struct object = 1;
+}
+
+service TestService {
+ rpc Call(StructType) returns (StructType);
+}
diff --git a/src/google/protobuf/util/internal/testdata/timestamp_duration.proto b/src/google/protobuf/util/internal/testdata/timestamp_duration.proto
new file mode 100644
index 00000000..56351f16
--- /dev/null
+++ b/src/google/protobuf/util/internal/testdata/timestamp_duration.proto
@@ -0,0 +1,47 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Proto to test proto3 Timestamp and Duration.
+syntax = "proto3";
+
+package google.protobuf.testing.timestampduration;
+option java_package = "com.google.protobuf.testing.timestampduration";
+
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/duration.proto";
+
+message TimestampDuration {
+ google.protobuf.Timestamp ts = 1;
+ google.protobuf.Duration dur = 2;
+}
+
+service TestService {
+ rpc Call(TimestampDuration) returns (TimestampDuration);
+}
diff --git a/src/google/protobuf/util/internal/testdata/wrappers.proto b/src/google/protobuf/util/internal/testdata/wrappers.proto
new file mode 100644
index 00000000..eabc99f2
--- /dev/null
+++ b/src/google/protobuf/util/internal/testdata/wrappers.proto
@@ -0,0 +1,100 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf.testing;
+
+import "google/protobuf/wrappers.proto";
+
+// Top-level test cases proto used by MarshallingTest. See description
+// at the top of the class MarshallingTest for details on how to write
+// test cases.
+message WrappersTestCases {
+ DoubleWrapper double_wrapper = 1;
+ FloatWrapper float_wrapper = 2;
+ Int64Wrapper int64_wrapper = 3;
+ UInt64Wrapper uint64_wrapper = 4;
+ Int32Wrapper int32_wrapper = 5;
+ UInt32Wrapper uint32_wrapper = 6;
+ BoolWrapper bool_wrapper = 7;
+ StringWrapper string_wrapper = 8;
+ BytesWrapper bytes_wrapper = 9;
+
+ DoubleWrapper double_wrapper_default = 10;
+ FloatWrapper float_wrapper_default = 11;
+ Int64Wrapper int64_wrapper_default = 12;
+ UInt64Wrapper uint64_wrapper_default = 13;
+ Int32Wrapper int32_wrapper_default = 14;
+ UInt32Wrapper uint32_wrapper_default = 15;
+ BoolWrapper bool_wrapper_default = 16;
+ StringWrapper string_wrapper_default = 17;
+ BytesWrapper bytes_wrapper_default = 18;
+}
+
+message DoubleWrapper {
+ google.protobuf.DoubleValue double = 1;
+}
+
+message FloatWrapper {
+ google.protobuf.FloatValue float = 1;
+}
+
+message Int64Wrapper {
+ google.protobuf.Int64Value int64 = 1;
+}
+
+message UInt64Wrapper {
+ google.protobuf.UInt64Value uint64 = 1;
+}
+
+message Int32Wrapper {
+ google.protobuf.Int32Value int32 = 1;
+}
+
+message UInt32Wrapper {
+ google.protobuf.UInt32Value uint32 = 1;
+}
+
+message BoolWrapper {
+ google.protobuf.BoolValue bool = 1;
+}
+
+message StringWrapper {
+ google.protobuf.StringValue string = 1;
+}
+
+message BytesWrapper {
+ google.protobuf.BytesValue bytes = 1;
+}
+
+service WrappersTestService {
+ rpc Call(WrappersTestCases) returns (WrappersTestCases);
+}
diff --git a/src/google/protobuf/util/internal/type_info.cc b/src/google/protobuf/util/internal/type_info.cc
new file mode 100644
index 00000000..6392e18c
--- /dev/null
+++ b/src/google/protobuf/util/internal/type_info.cc
@@ -0,0 +1,171 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/type_info.h>
+
+#include <map>
+#include <set>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/type.pb.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/statusor.h>
+#include <google/protobuf/util/internal/utility.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+namespace {
+
+// A TypeInfo that looks up information provided by a TypeResolver.
+class TypeInfoForTypeResolver : public TypeInfo {
+ public:
+ explicit TypeInfoForTypeResolver(TypeResolver* type_resolver)
+ : type_resolver_(type_resolver) {}
+
+ virtual ~TypeInfoForTypeResolver() {
+ DeleteCachedTypes(&cached_types_);
+ DeleteCachedTypes(&cached_enums_);
+ }
+
+ virtual util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl(
+ StringPiece type_url) {
+ map<StringPiece, StatusOrType>::iterator it = cached_types_.find(type_url);
+ if (it != cached_types_.end()) {
+ return it->second;
+ }
+ // Stores the string value so it can be referenced using StringPiece in the
+ // cached_types_ map.
+ const string& string_type_url =
+ *string_storage_.insert(type_url.ToString()).first;
+ google::protobuf::scoped_ptr<google::protobuf::Type> type(new google::protobuf::Type());
+ util::Status status =
+ type_resolver_->ResolveMessageType(string_type_url, type.get());
+ StatusOrType result =
+ status.ok() ? StatusOrType(type.release()) : StatusOrType(status);
+ cached_types_[string_type_url] = result;
+ return result;
+ }
+
+ virtual const google::protobuf::Type* GetType(StringPiece type_url) {
+ StatusOrType result = ResolveTypeUrl(type_url);
+ return result.ok() ? result.ValueOrDie() : NULL;
+ }
+
+ virtual const google::protobuf::Enum* GetEnum(StringPiece type_url) {
+ map<StringPiece, StatusOrEnum>::iterator it = cached_enums_.find(type_url);
+ if (it != cached_enums_.end()) {
+ return it->second.ok() ? it->second.ValueOrDie() : NULL;
+ }
+ // Stores the string value so it can be referenced using StringPiece in the
+ // cached_enums_ map.
+ const string& string_type_url =
+ *string_storage_.insert(type_url.ToString()).first;
+ google::protobuf::scoped_ptr<google::protobuf::Enum> enum_type(
+ new google::protobuf::Enum());
+ util::Status status =
+ type_resolver_->ResolveEnumType(string_type_url, enum_type.get());
+ StatusOrEnum result =
+ status.ok() ? StatusOrEnum(enum_type.release()) : StatusOrEnum(status);
+ cached_enums_[string_type_url] = result;
+ return result.ok() ? result.ValueOrDie() : NULL;
+ }
+
+ virtual const google::protobuf::Field* FindField(
+ const google::protobuf::Type* type, StringPiece camel_case_name) {
+ if (indexed_types_.find(type) == indexed_types_.end()) {
+ PopulateNameLookupTable(type);
+ indexed_types_.insert(type);
+ }
+ StringPiece name =
+ FindWithDefault(camel_case_name_table_, camel_case_name, StringPiece());
+ if (name.empty()) {
+ // Didn't find a mapping. Use whatever provided.
+ name = camel_case_name;
+ }
+ return FindFieldInTypeOrNull(type, name);
+ }
+
+ private:
+ typedef util::StatusOr<const google::protobuf::Type*> StatusOrType;
+ typedef util::StatusOr<const google::protobuf::Enum*> StatusOrEnum;
+
+ template <typename T>
+ static void DeleteCachedTypes(map<StringPiece, T>* cached_types) {
+ for (typename map<StringPiece, T>::iterator it = cached_types->begin();
+ it != cached_types->end(); ++it) {
+ if (it->second.ok()) {
+ delete it->second.ValueOrDie();
+ }
+ }
+ }
+
+ void PopulateNameLookupTable(const google::protobuf::Type* type) {
+ for (int i = 0; i < type->fields_size(); ++i) {
+ const google::protobuf::Field& field = type->fields(i);
+ StringPiece name = field.name();
+ StringPiece camel_case_name =
+ *string_storage_.insert(ToCamelCase(name)).first;
+ const StringPiece* existing = InsertOrReturnExisting(
+ &camel_case_name_table_, camel_case_name, name);
+ if (existing && *existing != name) {
+ GOOGLE_LOG(WARNING) << "Field '" << name << "' and '" << *existing
+ << "' map to the same camel case name '" << camel_case_name
+ << "'.";
+ }
+ }
+ }
+
+ TypeResolver* type_resolver_;
+
+ // Stores string values that will be referenced by StringPieces in
+ // cached_types_, cached_enums_ and camel_case_name_table_.
+ set<string> string_storage_;
+
+ map<StringPiece, StatusOrType> cached_types_;
+ map<StringPiece, StatusOrEnum> cached_enums_;
+
+ set<const google::protobuf::Type*> indexed_types_;
+ map<StringPiece, StringPiece> camel_case_name_table_;
+};
+} // namespace
+
+TypeInfo* TypeInfo::NewTypeInfo(TypeResolver* type_resolver) {
+ return new TypeInfoForTypeResolver(type_resolver);
+}
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/type_info.h b/src/google/protobuf/util/internal/type_info.h
new file mode 100644
index 00000000..67403fff
--- /dev/null
+++ b/src/google/protobuf/util/internal/type_info.h
@@ -0,0 +1,87 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_H__
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/type.pb.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/statusor.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+// Internal helper class for type resolving. Note that this class is not
+// thread-safe and should only be accessed in one thread.
+class LIBPROTOBUF_EXPORT TypeInfo {
+ public:
+ TypeInfo() {}
+ virtual ~TypeInfo() {}
+
+ // Resolves a type url into a Type. If the type url is invalid, returns
+ // INVALID_ARGUMENT error status. If the type url is valid but the
+ // corresponding type cannot be found, returns a NOT_FOUND error status.
+ //
+ // This TypeInfo class retains the ownership of the returned pointer.
+ virtual util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl(
+ StringPiece type_url) = 0;
+
+ // Resolves a type url into a Type. Like ResolveTypeUrl() but returns
+ // NULL if the type url is invalid or the type cannot be found.
+ //
+ // This TypeInfo class retains the ownership of the returned pointer.
+ virtual const google::protobuf::Type* GetType(StringPiece type_url) = 0;
+
+ // Resolves a type url for an enum. Returns NULL if the type url is
+ // invalid or the type cannot be found.
+ //
+ // This TypeInfo class retains the ownership of the returned pointer.
+ virtual const google::protobuf::Enum* GetEnum(StringPiece type_url) = 0;
+
+ // Looks up a field in the specified type given a CamelCase name.
+ virtual const google::protobuf::Field* FindField(
+ const google::protobuf::Type* type, StringPiece camel_case_name) = 0;
+
+ static TypeInfo* NewTypeInfo(TypeResolver* type_resolver);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeInfo);
+};
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_H__
diff --git a/src/google/protobuf/util/internal/type_info_test_helper.cc b/src/google/protobuf/util/internal/type_info_test_helper.cc
new file mode 100644
index 00000000..177b96e2
--- /dev/null
+++ b/src/google/protobuf/util/internal/type_info_test_helper.cc
@@ -0,0 +1,133 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/type_info_test_helper.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/util/internal/default_value_objectwriter.h>
+#include <google/protobuf/util/internal/type_info.h>
+#include <google/protobuf/util/internal/constants.h>
+#include <google/protobuf/util/internal/protostream_objectsource.h>
+#include <google/protobuf/util/internal/protostream_objectwriter.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/util/type_resolver_util.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+namespace testing {
+
+
+void TypeInfoTestHelper::ResetTypeInfo(
+ const vector<const Descriptor*>& descriptors) {
+ switch (type_) {
+ case USE_TYPE_RESOLVER: {
+ const DescriptorPool* pool = descriptors[0]->file()->pool();
+ for (int i = 1; i < descriptors.size(); ++i) {
+ GOOGLE_CHECK(pool == descriptors[i]->file()->pool())
+ << "Descriptors from different pools are not supported.";
+ }
+ type_resolver_.reset(
+ NewTypeResolverForDescriptorPool(kTypeServiceBaseUrl, pool));
+ typeinfo_.reset(TypeInfo::NewTypeInfo(type_resolver_.get()));
+ return;
+ }
+ }
+ GOOGLE_LOG(FATAL) << "Can not reach here.";
+}
+
+void TypeInfoTestHelper::ResetTypeInfo(const Descriptor* descriptor) {
+ vector<const Descriptor*> descriptors;
+ descriptors.push_back(descriptor);
+ ResetTypeInfo(descriptors);
+}
+
+void TypeInfoTestHelper::ResetTypeInfo(const Descriptor* descriptor1,
+ const Descriptor* descriptor2) {
+ vector<const Descriptor*> descriptors;
+ descriptors.push_back(descriptor1);
+ descriptors.push_back(descriptor2);
+ ResetTypeInfo(descriptors);
+}
+
+TypeInfo* TypeInfoTestHelper::GetTypeInfo() { return typeinfo_.get(); }
+
+ProtoStreamObjectSource* TypeInfoTestHelper::NewProtoSource(
+ io::CodedInputStream* coded_input, const string& type_url) {
+ const google::protobuf::Type* type = typeinfo_->GetType(type_url);
+ switch (type_) {
+ case USE_TYPE_RESOLVER: {
+ return new ProtoStreamObjectSource(coded_input, type_resolver_.get(),
+ *type);
+ }
+ }
+ GOOGLE_LOG(FATAL) << "Can not reach here.";
+ return NULL;
+}
+
+ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter(
+ const string& type_url, strings::ByteSink* output,
+ ErrorListener* listener) {
+ const google::protobuf::Type* type = typeinfo_->GetType(type_url);
+ switch (type_) {
+ case USE_TYPE_RESOLVER: {
+ return new ProtoStreamObjectWriter(type_resolver_.get(), *type, output,
+ listener);
+ }
+ }
+ GOOGLE_LOG(FATAL) << "Can not reach here.";
+ return NULL;
+}
+
+DefaultValueObjectWriter* TypeInfoTestHelper::NewDefaultValueWriter(
+ const string& type_url, ObjectWriter* writer) {
+ const google::protobuf::Type* type = typeinfo_->GetType(type_url);
+ switch (type_) {
+ case USE_TYPE_RESOLVER: {
+ return new DefaultValueObjectWriter(type_resolver_.get(), *type, writer);
+ }
+ }
+ GOOGLE_LOG(FATAL) << "Can not reach here.";
+ return NULL;
+}
+
+} // namespace testing
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/type_info_test_helper.h b/src/google/protobuf/util/internal/type_info_test_helper.h
new file mode 100644
index 00000000..6916a73b
--- /dev/null
+++ b/src/google/protobuf/util/internal/type_info_test_helper.h
@@ -0,0 +1,98 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/util/internal/type_info.h>
+#include <google/protobuf/util/internal/default_value_objectwriter.h>
+#include <google/protobuf/util/internal/protostream_objectsource.h>
+#include <google/protobuf/util/internal/protostream_objectwriter.h>
+#include <google/protobuf/util/type_resolver.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+namespace testing {
+
+enum TypeInfoSource {
+ USE_TYPE_RESOLVER,
+};
+
+// In the unit-tests we want to test two scenarios: one with type info from
+// ServiceTypeInfo, the other with type info from TypeResolver. This class
+// wraps the detail of where the type info is from and provides the same
+// interface so the same unit-test code can test both scenarios.
+class TypeInfoTestHelper {
+ public:
+ explicit TypeInfoTestHelper(TypeInfoSource type) : type_(type) {}
+
+ // Creates a TypeInfo object for the given set of descriptors.
+ void ResetTypeInfo(const vector<const Descriptor*>& descriptors);
+
+ // Convinent overloads.
+ void ResetTypeInfo(const Descriptor* descriptor);
+ void ResetTypeInfo(const Descriptor* descriptor1,
+ const Descriptor* descriptor2);
+
+ // Returns the TypeInfo created after ResetTypeInfo.
+ TypeInfo* GetTypeInfo();
+
+ ProtoStreamObjectSource* NewProtoSource(io::CodedInputStream* coded_input,
+ const string& type_url);
+
+ ProtoStreamObjectWriter* NewProtoWriter(const string& type_url,
+ strings::ByteSink* output,
+ ErrorListener* listener);
+
+ DefaultValueObjectWriter* NewDefaultValueWriter(const string& type_url,
+ ObjectWriter* writer);
+
+ private:
+ TypeInfoSource type_;
+ google::protobuf::scoped_ptr<TypeInfo> typeinfo_;
+ google::protobuf::scoped_ptr<TypeResolver> type_resolver_;
+};
+} // namespace testing
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__
diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc
new file mode 100644
index 00000000..794777d4
--- /dev/null
+++ b/src/google/protobuf/util/internal/utility.cc
@@ -0,0 +1,333 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/internal/utility.h>
+
+#include <cmath>
+#include <algorithm>
+#include <utility>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/wrappers.pb.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/util/internal/constants.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/mathlimits.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace converter {
+
+namespace {
+const StringPiece SkipWhiteSpace(StringPiece str) {
+ StringPiece::size_type i;
+ for (i = 0; i < str.size() && isspace(str[i]); ++i) {}
+ GOOGLE_DCHECK(i == str.size() || !isspace(str[i]));
+ return StringPiece(str, i);
+}
+} // namespace
+
+bool GetBoolOptionOrDefault(
+ const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+ const string& option_name, bool default_value) {
+ const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
+ if (opt == NULL) {
+ return default_value;
+ }
+ return GetBoolFromAny(opt->value());
+}
+
+int64 GetInt64OptionOrDefault(
+ const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+ const string& option_name, int64 default_value) {
+ const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
+ if (opt == NULL) {
+ return default_value;
+ }
+ return GetInt64FromAny(opt->value());
+}
+
+double GetDoubleOptionOrDefault(
+ const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+ const string& option_name, double default_value) {
+ const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
+ if (opt == NULL) {
+ return default_value;
+ }
+ return GetDoubleFromAny(opt->value());
+}
+
+string GetStringOptionOrDefault(
+ const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+ const string& option_name, const string& default_value) {
+ const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
+ if (opt == NULL) {
+ return default_value;
+ }
+ return GetStringFromAny(opt->value());
+}
+
+template <typename T>
+void ParseFromAny(const string& data, T* result) {
+ result->ParseFromString(data);
+}
+
+// Returns a boolean value contained in Any type.
+// TODO(skarvaje): Add type checking & error messages here.
+bool GetBoolFromAny(const google::protobuf::Any& any) {
+ google::protobuf::BoolValue b;
+ ParseFromAny(any.value(), &b);
+ return b.value();
+}
+
+int64 GetInt64FromAny(const google::protobuf::Any& any) {
+ google::protobuf::Int64Value i;
+ ParseFromAny(any.value(), &i);
+ return i.value();
+}
+
+double GetDoubleFromAny(const google::protobuf::Any& any) {
+ google::protobuf::DoubleValue i;
+ ParseFromAny(any.value(), &i);
+ return i.value();
+}
+
+string GetStringFromAny(const google::protobuf::Any& any) {
+ google::protobuf::StringValue s;
+ ParseFromAny(any.value(), &s);
+ return s.value();
+}
+
+const StringPiece GetTypeWithoutUrl(StringPiece type_url) {
+ size_t idx = type_url.rfind('/');
+ return type_url.substr(idx + 1);
+}
+
+const string GetFullTypeWithUrl(StringPiece simple_type) {
+ return StrCat(kTypeServiceBaseUrl, "/", simple_type);
+}
+
+const google::protobuf::Option* FindOptionOrNull(
+ const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+ const string& option_name) {
+ for (int i = 0; i < options.size(); ++i) {
+ const google::protobuf::Option& opt = options.Get(i);
+ if (opt.name() == option_name) {
+ return &opt;
+ }
+ }
+ return NULL;
+}
+
+const google::protobuf::Field* FindFieldInTypeOrNull(
+ const google::protobuf::Type* type, StringPiece field_name) {
+ if (type != NULL) {
+ for (int i = 0; i < type->fields_size(); ++i) {
+ const google::protobuf::Field& field = type->fields(i);
+ if (field.name() == field_name) {
+ return &field;
+ }
+ }
+ }
+ return NULL;
+}
+
+const google::protobuf::EnumValue* FindEnumValueByNameOrNull(
+ const google::protobuf::Enum* enum_type, StringPiece enum_name) {
+ if (enum_type != NULL) {
+ for (int i = 0; i < enum_type->enumvalue_size(); ++i) {
+ const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i);
+ if (enum_value.name() == enum_name) {
+ return &enum_value;
+ }
+ }
+ }
+ return NULL;
+}
+
+const google::protobuf::EnumValue* FindEnumValueByNumberOrNull(
+ const google::protobuf::Enum* enum_type, int32 value) {
+ if (enum_type != NULL) {
+ for (int i = 0; i < enum_type->enumvalue_size(); ++i) {
+ const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i);
+ if (enum_value.number() == value) {
+ return &enum_value;
+ }
+ }
+ }
+ return NULL;
+}
+
+string ToCamelCase(const StringPiece input) {
+ bool capitalize_next = false;
+ bool was_cap = true;
+ bool is_cap = false;
+ bool first_word = true;
+ string result;
+ result.reserve(input.size());
+
+ for (size_t i = 0; i < input.size(); ++i, was_cap = is_cap) {
+ is_cap = ascii_isupper(input[i]);
+ if (input[i] == '_') {
+ capitalize_next = true;
+ if (!result.empty()) first_word = false;
+ continue;
+ } else if (first_word) {
+ // Consider when the current character B is capitalized,
+ // first word ends when:
+ // 1) following a lowercase: "...aB..."
+ // 2) followed by a lowercase: "...ABc..."
+ if (!result.empty() && is_cap &&
+ (!was_cap || (i + 1 < input.size() && ascii_islower(input[i + 1])))) {
+ first_word = false;
+ } else {
+ result.push_back(ascii_tolower(input[i]));
+ continue;
+ }
+ } else if (capitalize_next) {
+ capitalize_next = false;
+ if (ascii_islower(input[i])) {
+ result.push_back(ascii_toupper(input[i]));
+ continue;
+ }
+ }
+ result.push_back(input[i]);
+ }
+ return result;
+}
+
+string ToSnakeCase(StringPiece input) {
+ bool was_not_underscore = false; // Initialize to false for case 1 (below)
+ bool was_not_cap = false;
+ string result;
+ result.reserve(input.size() << 1);
+
+ for (size_t i = 0; i < input.size(); ++i) {
+ if (ascii_isupper(input[i])) {
+ // Consider when the current character B is capitalized:
+ // 1) At beginning of input: "B..." => "b..."
+ // (e.g. "Biscuit" => "biscuit")
+ // 2) Following a lowercase: "...aB..." => "...a_b..."
+ // (e.g. "gBike" => "g_bike")
+ // 3) At the end of input: "...AB" => "...ab"
+ // (e.g. "GoogleLAB" => "google_lab")
+ // 4) Followed by a lowercase: "...ABc..." => "...a_bc..."
+ // (e.g. "GBike" => "g_bike")
+ if (was_not_underscore && // case 1 out
+ (was_not_cap || // case 2 in, case 3 out
+ (i + 1 < input.size() && // case 3 out
+ ascii_islower(input[i + 1])))) { // case 4 in
+ // We add an underscore for case 2 and case 4.
+ result.push_back('_');
+ }
+ result.push_back(ascii_tolower(input[i]));
+ was_not_underscore = true;
+ was_not_cap = false;
+ } else {
+ result.push_back(input[i]);
+ was_not_underscore = input[i] != '_';
+ was_not_cap = true;
+ }
+ }
+ return result;
+}
+
+set<string>* well_known_types_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(well_known_types_init_);
+const char* well_known_types_name_array_[] = {
+ "google.protobuf.Timestamp", "google.protobuf.Duration",
+ "google.protobuf.DoubleValue", "google.protobuf.FloatValue",
+ "google.protobuf.Int64Value", "google.protobuf.UInt64Value",
+ "google.protobuf.Int32Value", "google.protobuf.UInt32Value",
+ "google.protobuf.BoolValue", "google.protobuf.StringValue",
+ "google.protobuf.BytesValue", "google.protobuf.FieldMask"};
+
+void DeleteWellKnownTypes() { delete well_known_types_; }
+
+void InitWellKnownTypes() {
+ well_known_types_ = new set<string>;
+ for (int i = 0; i < GOOGLE_ARRAYSIZE(well_known_types_name_array_); ++i) {
+ well_known_types_->insert(well_known_types_name_array_[i]);
+ }
+ google::protobuf::internal::OnShutdown(&DeleteWellKnownTypes);
+}
+
+bool IsWellKnownType(const string& type_name) {
+ InitWellKnownTypes();
+ return ContainsKey(*well_known_types_, type_name);
+}
+
+bool IsValidBoolString(const string& bool_string) {
+ return bool_string == "true" || bool_string == "false" ||
+ bool_string == "1" || bool_string == "0";
+}
+
+bool IsMap(const google::protobuf::Field& field,
+ const google::protobuf::Type& type) {
+ return (field.cardinality() ==
+ google::protobuf::Field_Cardinality_CARDINALITY_REPEATED &&
+ GetBoolOptionOrDefault(type.options(),
+ "google.protobuf.MessageOptions.map_entry", false));
+}
+
+string DoubleAsString(double value) {
+ if (value == std::numeric_limits<double>::infinity()) return "Infinity";
+ if (value == -std::numeric_limits<double>::infinity()) return "-Infinity";
+ if (google::protobuf::MathLimits<double>::IsNaN(value)) return "NaN";
+
+ return SimpleDtoa(value);
+}
+
+string FloatAsString(float value) {
+ if (isfinite(value)) return SimpleFtoa(value);
+ return DoubleAsString(value);
+}
+
+bool SafeStrToFloat(StringPiece str, float *value) {
+ double double_value;
+ if (!safe_strtod(str, &double_value)) {
+ return false;
+ }
+ *value = static_cast<float>(double_value);
+
+ if ((*value == numeric_limits<float>::infinity()) ||
+ (*value == -numeric_limits<float>::infinity())) {
+ return false;
+ }
+ return true;
+}
+
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/internal/utility.h b/src/google/protobuf/util/internal/utility.h
new file mode 100644
index 00000000..d0d88c19
--- /dev/null
+++ b/src/google/protobuf/util/internal/utility.h
@@ -0,0 +1,187 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__
+#define GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+#include <utility>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/type.pb.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/stubs/stringpiece.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/statusor.h>
+
+
+namespace google {
+namespace protobuf {
+class Method;
+class Any;
+class Bool;
+class Option;
+class Field;
+class Type;
+class Enum;
+class EnumValue;
+} // namespace protobuf
+
+
+namespace protobuf {
+namespace util {
+namespace converter {
+// Finds the tech option identified by option_name. Parses the boolean value and
+// returns it.
+// When the option with the given name is not found, default_value is returned.
+LIBPROTOBUF_EXPORT bool GetBoolOptionOrDefault(
+ const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+ const string& option_name, bool default_value);
+
+// Returns int64 option value. If the option isn't found, returns the
+// default_value.
+LIBPROTOBUF_EXPORT int64 GetInt64OptionOrDefault(
+ const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+ const string& option_name, int64 default_value);
+
+// Returns double option value. If the option isn't found, returns the
+// default_value.
+LIBPROTOBUF_EXPORT double GetDoubleOptionOrDefault(
+ const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+ const string& option_name, double default_value);
+
+// Returns string option value. If the option isn't found, returns the
+// default_value.
+LIBPROTOBUF_EXPORT string GetStringOptionOrDefault(
+ const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+ const string& option_name, const string& default_value);
+
+// Returns a boolean value contained in Any type.
+// TODO(skarvaje): Make these utilities dealing with Any types more generic,
+// add more error checking and move to a more public/sharable location so others
+// can use.
+LIBPROTOBUF_EXPORT bool GetBoolFromAny(const google::protobuf::Any& any);
+
+// Returns int64 value contained in Any type.
+LIBPROTOBUF_EXPORT int64 GetInt64FromAny(const google::protobuf::Any& any);
+
+// Returns double value contained in Any type.
+LIBPROTOBUF_EXPORT double GetDoubleFromAny(const google::protobuf::Any& any);
+
+// Returns string value contained in Any type.
+LIBPROTOBUF_EXPORT string GetStringFromAny(const google::protobuf::Any& any);
+
+// Returns the type string without the url prefix. e.g.: If the passed type is
+// 'type.googleapis.com/tech.type.Bool', the returned value is 'tech.type.Bool'.
+LIBPROTOBUF_EXPORT const StringPiece GetTypeWithoutUrl(StringPiece type_url);
+
+// Returns the simple_type with the base type url (kTypeServiceBaseUrl)
+// prefixed.
+//
+// E.g:
+// GetFullTypeWithUrl("google.protobuf.Timestamp") returns the string
+// "type.googleapis.com/google.protobuf.Timestamp".
+LIBPROTOBUF_EXPORT const string GetFullTypeWithUrl(StringPiece simple_type);
+
+// Finds and returns option identified by name and option_name within the
+// provided map. Returns NULL if none found.
+LIBPROTOBUF_EXPORT const google::protobuf::Option* FindOptionOrNull(
+ const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
+ const string& option_name);
+
+// Finds and returns the field identified by field_name in the passed tech Type
+// object. Returns NULL if none found.
+LIBPROTOBUF_EXPORT const google::protobuf::Field* FindFieldInTypeOrNull(
+ const google::protobuf::Type* type, StringPiece field_name);
+
+// Finds and returns the EnumValue identified by enum_name in the passed tech
+// Enum object. Returns NULL if none found.
+LIBPROTOBUF_EXPORT const google::protobuf::EnumValue* FindEnumValueByNameOrNull(
+ const google::protobuf::Enum* enum_type, StringPiece enum_name);
+
+// Finds and returns the EnumValue identified by value in the passed tech
+// Enum object. Returns NULL if none found.
+LIBPROTOBUF_EXPORT const google::protobuf::EnumValue* FindEnumValueByNumberOrNull(
+ const google::protobuf::Enum* enum_type, int32 value);
+
+// Converts input to camel-case and returns it.
+// Tests are in wrappers/translator/snake2camel_objectwriter_test.cc
+// TODO(skarvaje): Isolate tests for this function and put them in
+// utility_test.cc
+LIBPROTOBUF_EXPORT string ToCamelCase(const StringPiece input);
+
+// Converts input to snake_case and returns it.
+LIBPROTOBUF_EXPORT string ToSnakeCase(StringPiece input);
+
+// Returns true if type_name represents a well-known type.
+LIBPROTOBUF_EXPORT bool IsWellKnownType(const string& type_name);
+
+// Returns true if 'bool_string' represents a valid boolean value. Only "true",
+// "false", "0" and "1" are allowed.
+LIBPROTOBUF_EXPORT bool IsValidBoolString(const string& bool_string);
+
+// Returns true if "field" is a protobuf map field based on its type.
+bool IsMap(const google::protobuf::Field& field,
+ const google::protobuf::Type& type);
+
+// Infinity/NaN-aware conversion to string.
+LIBPROTOBUF_EXPORT string DoubleAsString(double value);
+LIBPROTOBUF_EXPORT string FloatAsString(float value);
+
+// Convert from int32, int64, uint32, uint64, double or float to string.
+template <typename T>
+string ValueAsString(T value) {
+ return SimpleItoa(value);
+}
+
+template <>
+inline string ValueAsString(float value) {
+ return FloatAsString(value);
+}
+
+template <>
+inline string ValueAsString(double value) {
+ return DoubleAsString(value);
+}
+
+// Converts a string to float. Unlike safe_strtof, conversion will fail if the
+// value fits into double but not float (e.g., DBL_MAX).
+LIBPROTOBUF_EXPORT bool SafeStrToFloat(StringPiece str, float* value);
+} // namespace converter
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__
diff --git a/src/google/protobuf/util/json_format_proto3.proto b/src/google/protobuf/util/json_format_proto3.proto
new file mode 100644
index 00000000..7a282868
--- /dev/null
+++ b/src/google/protobuf/util/json_format_proto3.proto
@@ -0,0 +1,157 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package proto3;
+
+
+import "google/protobuf/duration.proto";
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/wrappers.proto";
+import "google/protobuf/struct.proto";
+import "google/protobuf/any.proto";
+import "google/protobuf/field_mask.proto";
+
+enum EnumType {
+ FOO = 0;
+ BAR = 1;
+}
+
+message MessageType {
+ int32 value = 1;
+}
+
+message TestMessage {
+ bool bool_value = 1;
+ int32 int32_value = 2;
+ int64 int64_value = 3;
+ uint32 uint32_value = 4;
+ uint64 uint64_value = 5;
+ float float_value = 6;
+ double double_value = 7;
+ string string_value = 8;
+ bytes bytes_value = 9;
+ EnumType enum_value = 10;
+ MessageType message_value = 11;
+
+ repeated bool repeated_bool_value = 21;
+ repeated int32 repeated_int32_value = 22;
+ repeated int64 repeated_int64_value = 23;
+ repeated uint32 repeated_uint32_value = 24;
+ repeated uint64 repeated_uint64_value = 25;
+ repeated float repeated_float_value = 26;
+ repeated double repeated_double_value = 27;
+ repeated string repeated_string_value = 28;
+ repeated bytes repeated_bytes_value = 29;
+ repeated EnumType repeated_enum_value = 30;
+ repeated MessageType repeated_message_value = 31;
+}
+
+message TestOneof {
+ // In JSON format oneof fields behave mostly the same as optional
+ // fields except that:
+ // 1. Oneof fields have field presence information and will be
+ // printed if it's set no matter whether it's the default value.
+ // 2. Multiple oneof fields in the same oneof cannot appear at the
+ // same time in the input.
+ oneof oneof_value {
+ int32 oneof_int32_value = 1;
+ string oneof_string_value = 2;
+ bytes oneof_bytes_value = 3;
+ EnumType oneof_enum_value = 4;
+ MessageType oneof_message_value = 5;
+ }
+}
+
+message TestMap {
+ map<bool, int32> bool_map = 1;
+ map<int32, int32> int32_map = 2;
+ map<int64, int32> int64_map = 3;
+ map<uint32, int32> uint32_map = 4;
+ map<uint64, int32> uint64_map = 5;
+ map<string, int32> string_map = 6;
+}
+
+message TestWrapper {
+ google.protobuf.BoolValue bool_value = 1;
+ google.protobuf.Int32Value int32_value = 2;
+ google.protobuf.Int64Value int64_value = 3;
+ google.protobuf.UInt32Value uint32_value = 4;
+ google.protobuf.UInt64Value uint64_value = 5;
+ google.protobuf.FloatValue float_value = 6;
+ google.protobuf.DoubleValue double_value = 7;
+ google.protobuf.StringValue string_value = 8;
+ google.protobuf.BytesValue bytes_value = 9;
+
+ repeated google.protobuf.BoolValue repeated_bool_value = 11;
+ repeated google.protobuf.Int32Value repeated_int32_value = 12;
+ repeated google.protobuf.Int64Value repeated_int64_value = 13;
+ repeated google.protobuf.UInt32Value repeated_uint32_value = 14;
+ repeated google.protobuf.UInt64Value repeated_uint64_value = 15;
+ repeated google.protobuf.FloatValue repeated_float_value = 16;
+ repeated google.protobuf.DoubleValue repeated_double_value = 17;
+ repeated google.protobuf.StringValue repeated_string_value = 18;
+ repeated google.protobuf.BytesValue repeated_bytes_value = 19;
+}
+
+message TestTimestamp {
+ google.protobuf.Timestamp value = 1;
+ repeated google.protobuf.Timestamp repeated_value = 2;
+}
+
+message TestDuration {
+ google.protobuf.Duration value = 1;
+ repeated google.protobuf.Duration repeated_value = 2;
+}
+
+message TestFieldMask {
+ google.protobuf.FieldMask value = 1;
+}
+
+message TestStruct {
+ google.protobuf.Struct value = 1;
+ repeated google.protobuf.Struct repeated_value = 2;
+}
+
+message TestAny {
+ google.protobuf.Any value = 1;
+ repeated google.protobuf.Any repeated_value = 2;
+}
+
+message TestValue {
+ google.protobuf.Value value = 1;
+ repeated google.protobuf.Value repeated_value = 2;
+}
+
+message TestListValue {
+ google.protobuf.ListValue value = 1;
+ repeated google.protobuf.ListValue repeated_value = 2;
+}
diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc
new file mode 100644
index 00000000..6cd40fd5
--- /dev/null
+++ b/src/google/protobuf/util/json_util.cc
@@ -0,0 +1,142 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/json_util.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/util/internal/default_value_objectwriter.h>
+#include <google/protobuf/util/internal/snake2camel_objectwriter.h>
+#include <google/protobuf/util/internal/error_listener.h>
+#include <google/protobuf/util/internal/json_objectwriter.h>
+#include <google/protobuf/util/internal/json_stream_parser.h>
+#include <google/protobuf/util/internal/protostream_objectsource.h>
+#include <google/protobuf/util/internal/protostream_objectwriter.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/util/type_resolver_util.h>
+#include <google/protobuf/stubs/bytestream.h>
+#include <google/protobuf/stubs/status_macros.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+
+namespace internal {
+void ZeroCopyStreamByteSink::Append(const char* bytes, size_t len) {
+ while (len > 0) {
+ void* buffer;
+ int length;
+ if (!stream_->Next(&buffer, &length)) {
+ // There isn't a way for ByteSink to report errors.
+ return;
+ }
+ if (len < length) {
+ memcpy(buffer, bytes, len);
+ stream_->BackUp(length - len);
+ break;
+ } else {
+ memcpy(buffer, bytes, length);
+ bytes += length;
+ len -= length;
+ }
+ }
+}
+} // namespace internal
+
+util::Status BinaryToJsonStream(TypeResolver* resolver,
+ const string& type_url,
+ io::ZeroCopyInputStream* binary_input,
+ io::ZeroCopyOutputStream* json_output,
+ const JsonOptions& options) {
+ io::CodedInputStream in_stream(binary_input);
+ google::protobuf::Type type;
+ RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type));
+ converter::ProtoStreamObjectSource proto_source(&in_stream, resolver, type);
+ io::CodedOutputStream out_stream(json_output);
+ converter::JsonObjectWriter json_writer(options.add_whitespace ? " " : "",
+ &out_stream);
+ converter::Snake2CamelObjectWriter snake2camel_writer(&json_writer);
+ if (options.always_print_primitive_fields) {
+ converter::DefaultValueObjectWriter default_value_writer(
+ resolver, type, &snake2camel_writer);
+ return proto_source.WriteTo(&default_value_writer);
+ } else {
+ return proto_source.WriteTo(&snake2camel_writer);
+ }
+}
+
+util::Status BinaryToJsonString(TypeResolver* resolver,
+ const string& type_url,
+ const string& binary_input,
+ string* json_output,
+ const JsonOptions& options) {
+ io::ArrayInputStream input_stream(binary_input.data(), binary_input.size());
+ io::StringOutputStream output_stream(json_output);
+ return BinaryToJsonStream(resolver, type_url, &input_stream, &output_stream,
+ options);
+}
+
+util::Status JsonToBinaryStream(TypeResolver* resolver,
+ const string& type_url,
+ io::ZeroCopyInputStream* json_input,
+ io::ZeroCopyOutputStream* binary_output) {
+ google::protobuf::Type type;
+ RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type));
+ internal::ZeroCopyStreamByteSink sink(binary_output);
+ converter::NoopErrorListener listener;
+ converter::ProtoStreamObjectWriter proto_writer(resolver, type, &sink,
+ &listener);
+
+ converter::JsonStreamParser parser(&proto_writer);
+ const void* buffer;
+ int length;
+ while (json_input->Next(&buffer, &length)) {
+ if (length == 0) continue;
+ RETURN_IF_ERROR(
+ parser.Parse(StringPiece(static_cast<const char*>(buffer), length)));
+ }
+ RETURN_IF_ERROR(parser.FinishParse());
+
+ return util::Status::OK;
+}
+
+util::Status JsonToBinaryString(TypeResolver* resolver,
+ const string& type_url,
+ const string& json_input,
+ string* binary_output) {
+ io::ArrayInputStream input_stream(json_input.data(), json_input.size());
+ io::StringOutputStream output_stream(binary_output);
+ return JsonToBinaryStream(resolver, type_url, &input_stream, &output_stream);
+}
+
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/json_util.h b/src/google/protobuf/util/json_util.h
new file mode 100644
index 00000000..6796ea08
--- /dev/null
+++ b/src/google/protobuf/util/json_util.h
@@ -0,0 +1,136 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Utility functions to convert between protobuf binary format and proto3 JSON
+// format.
+#ifndef GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__
+#define GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__
+
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/bytestream.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+class ZeroCopyInputStream;
+class ZeroCopyOutputStream;
+} // namespace io
+namespace util {
+
+struct LIBPROTOBUF_EXPORT JsonOptions {
+ // Whether to add spaces, line breaks and indentation to make the JSON output
+ // easy to read.
+ bool add_whitespace;
+ // Whether to always print primitive fields. By default primitive fields with
+ // default values will be omitted in JSON joutput. For example, an int32 field
+ // set to 0 will be omitted. Set this flag to true will override the default
+ // behavior and print primitive fields regardless of their values.
+ bool always_print_primitive_fields;
+
+ JsonOptions() : add_whitespace(false),
+ always_print_primitive_fields(false) {
+ }
+};
+
+// Converts protobuf binary data to JSON.
+// The conversion will fail if:
+// 1. TypeResolver fails to resolve a type.
+// 2. input is not valid protobuf wire format, or conflicts with the type
+// information returned by TypeResolver.
+// Note that unknown fields will be discarded silently.
+LIBPROTOBUF_EXPORT util::Status BinaryToJsonStream(
+ TypeResolver* resolver,
+ const string& type_url,
+ io::ZeroCopyInputStream* binary_input,
+ io::ZeroCopyOutputStream* json_output,
+ const JsonOptions& options);
+
+inline util::Status BinaryToJsonStream(
+ TypeResolver* resolver, const string& type_url,
+ io::ZeroCopyInputStream* binary_input,
+ io::ZeroCopyOutputStream* json_output) {
+ return BinaryToJsonStream(resolver, type_url, binary_input, json_output,
+ JsonOptions());
+}
+
+LIBPROTOBUF_EXPORT util::Status BinaryToJsonString(
+ TypeResolver* resolver,
+ const string& type_url,
+ const string& binary_input,
+ string* json_output,
+ const JsonOptions& options);
+
+inline util::Status BinaryToJsonString(TypeResolver* resolver,
+ const string& type_url,
+ const string& binary_input,
+ string* json_output) {
+ return BinaryToJsonString(resolver, type_url, binary_input, json_output,
+ JsonOptions());
+}
+
+// Converts JSON data to protobuf binary format.
+// The conversion will fail if:
+// 1. TypeResolver fails to resolve a type.
+// 2. input is not valid JSON format, or conflicts with the type
+// information returned by TypeResolver.
+// 3. input has unknown fields.
+LIBPROTOBUF_EXPORT util::Status JsonToBinaryStream(
+ TypeResolver* resolver,
+ const string& type_url,
+ io::ZeroCopyInputStream* json_input,
+ io::ZeroCopyOutputStream* binary_output);
+
+LIBPROTOBUF_EXPORT util::Status JsonToBinaryString(
+ TypeResolver* resolver,
+ const string& type_url,
+ const string& json_input,
+ string* binary_output);
+
+namespace internal {
+// Internal helper class. Put in the header so we can write unit-tests for it.
+class LIBPROTOBUF_EXPORT ZeroCopyStreamByteSink : public strings::ByteSink {
+ public:
+ explicit ZeroCopyStreamByteSink(io::ZeroCopyOutputStream* stream)
+ : stream_(stream) {}
+
+ virtual void Append(const char* bytes, size_t len);
+
+ private:
+ io::ZeroCopyOutputStream* stream_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyStreamByteSink);
+};
+} // namespace internal
+
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__
diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc
new file mode 100644
index 00000000..8399b408
--- /dev/null
+++ b/src/google/protobuf/util/json_util_test.cc
@@ -0,0 +1,277 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/json_util.h>
+
+#include <list>
+#include <string>
+
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/util/json_format_proto3.pb.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/util/type_resolver_util.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace {
+
+using proto3::FOO;
+using proto3::BAR;
+using proto3::TestMessage;
+
+static const char kTypeUrlPrefix[] = "type.googleapis.com";
+
+static string GetTypeUrl(const Descriptor* message) {
+ return string(kTypeUrlPrefix) + "/" + message->full_name();
+}
+
+// As functions defined in json_util.h are just thin wrappers around the
+// JSON conversion code in //net/proto2/util/converter, in this test we
+// only cover some very basic cases to make sure the wrappers have forwarded
+// parameters to the underlying implementation correctly. More detailed
+// tests are contained in the //net/proto2/util/converter directory.
+class JsonUtilTest : public testing::Test {
+ protected:
+ JsonUtilTest() {
+ resolver_.reset(NewTypeResolverForDescriptorPool(
+ kTypeUrlPrefix, DescriptorPool::generated_pool()));
+ }
+
+ string ToJson(const Message& message, const JsonOptions& options) {
+ string result;
+ GOOGLE_CHECK_OK(BinaryToJsonString(resolver_.get(),
+ GetTypeUrl(message.GetDescriptor()),
+ message.SerializeAsString(), &result, options));
+ return result;
+ }
+
+ bool FromJson(const string& json, Message* message) {
+ string binary;
+ GOOGLE_CHECK_OK(JsonToBinaryString(
+ resolver_.get(), GetTypeUrl(message->GetDescriptor()), json, &binary));
+ return message->ParseFromString(binary);
+ }
+
+ google::protobuf::scoped_ptr<TypeResolver> resolver_;
+};
+
+TEST_F(JsonUtilTest, TestWhitespaces) {
+ TestMessage m;
+ m.mutable_message_value();
+
+ JsonOptions options;
+ EXPECT_EQ("{\"messageValue\":{}}", ToJson(m, options));
+ options.add_whitespace = true;
+ EXPECT_EQ(
+ "{\n"
+ " \"messageValue\": {}\n"
+ "}\n",
+ ToJson(m, options));
+}
+
+TEST_F(JsonUtilTest, TestDefaultValues) {
+ TestMessage m;
+ JsonOptions options;
+ EXPECT_EQ("{}", ToJson(m, options));
+ options.always_print_primitive_fields = true;
+ EXPECT_EQ(
+ "{\"boolValue\":false,"
+ "\"int32Value\":0,"
+ "\"int64Value\":\"0\","
+ "\"uint32Value\":0,"
+ "\"uint64Value\":\"0\","
+ "\"floatValue\":0,"
+ "\"doubleValue\":0,"
+ "\"stringValue\":\"\","
+ "\"bytesValue\":\"\","
+ // TODO(xiaofeng): The default enum value should be FOO. I believe
+ // this is a bug in DefaultValueObjectWriter.
+ "\"enumValue\":null"
+ "}",
+ ToJson(m, options));
+}
+
+TEST_F(JsonUtilTest, ParseMessage) {
+ // Some random message but good enough to verify that the parsing warpper
+ // functions are working properly.
+ string input =
+ "{\n"
+ " \"int32Value\": 1024,\n"
+ " \"repeatedInt32Value\": [1, 2],\n"
+ " \"messageValue\": {\n"
+ " \"value\": 2048\n"
+ " },\n"
+ " \"repeatedMessageValue\": [\n"
+ " {\"value\": 40}, {\"value\": 96}\n"
+ " ]\n"
+ "}\n";
+ TestMessage m;
+ ASSERT_TRUE(FromJson(input, &m));
+ EXPECT_EQ(1024, m.int32_value());
+ ASSERT_EQ(2, m.repeated_int32_value_size());
+ EXPECT_EQ(1, m.repeated_int32_value(0));
+ EXPECT_EQ(2, m.repeated_int32_value(1));
+ EXPECT_EQ(2048, m.message_value().value());
+ ASSERT_EQ(2, m.repeated_message_value_size());
+ EXPECT_EQ(40, m.repeated_message_value(0).value());
+ EXPECT_EQ(96, m.repeated_message_value(1).value());
+}
+
+typedef pair<char*, int> Segment;
+// A ZeroCopyOutputStream that writes to multiple buffers.
+class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream {
+ public:
+ explicit SegmentedZeroCopyOutputStream(list<Segment> segments)
+ : segments_(segments), last_segment_(NULL, 0), byte_count_(0) {}
+
+ virtual bool Next(void** buffer, int* length) {
+ if (segments_.empty()) {
+ return false;
+ }
+ last_segment_ = segments_.front();
+ segments_.pop_front();
+ *buffer = last_segment_.first;
+ *length = last_segment_.second;
+ byte_count_ += *length;
+ return true;
+ }
+
+ virtual void BackUp(int length) {
+ GOOGLE_CHECK(length <= last_segment_.second);
+ segments_.push_front(
+ Segment(last_segment_.first + last_segment_.second - length, length));
+ last_segment_ = Segment(last_segment_.first, last_segment_.second - length);
+ byte_count_ -= length;
+ }
+
+ virtual int64 ByteCount() const { return byte_count_; }
+
+ private:
+ list<Segment> segments_;
+ Segment last_segment_;
+ int64 byte_count_;
+};
+
+// This test splits the output buffer and also the input data into multiple
+// segments and checks that the implementation of ZeroCopyStreamByteSink
+// handles all possible cases correctly.
+TEST(ZeroCopyStreamByteSinkTest, TestAllInputOutputPatterns) {
+ static const int kOutputBufferLength = 10;
+ // An exhaustive test takes too long, skip some combinations to make the test
+ // run faster.
+ static const int kSkippedPatternCount = 7;
+
+ char buffer[kOutputBufferLength];
+ for (int split_pattern = 0; split_pattern < (1 << (kOutputBufferLength - 1));
+ split_pattern += kSkippedPatternCount) {
+ // Split the buffer into small segments according to the split_pattern.
+ list<Segment> segments;
+ int segment_start = 0;
+ for (int i = 0; i < kOutputBufferLength - 1; ++i) {
+ if (split_pattern & (1 << i)) {
+ segments.push_back(
+ Segment(buffer + segment_start, i - segment_start + 1));
+ segment_start = i + 1;
+ }
+ }
+ segments.push_back(
+ Segment(buffer + segment_start, kOutputBufferLength - segment_start));
+
+ // Write exactly 10 bytes through the ByteSink.
+ string input_data = "0123456789";
+ for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
+ input_pattern += kSkippedPatternCount) {
+ memset(buffer, 0, sizeof(buffer));
+ {
+ SegmentedZeroCopyOutputStream output_stream(segments);
+ internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
+ int start = 0;
+ for (int j = 0; j < input_data.length() - 1; ++j) {
+ if (input_pattern & (1 << j)) {
+ byte_sink.Append(&input_data[start], j - start + 1);
+ start = j + 1;
+ }
+ }
+ byte_sink.Append(&input_data[start], input_data.length() - start);
+ }
+ EXPECT_EQ(input_data, string(buffer, input_data.length()));
+ }
+
+ // Write only 9 bytes through the ByteSink.
+ input_data = "012345678";
+ for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
+ input_pattern += kSkippedPatternCount) {
+ memset(buffer, 0, sizeof(buffer));
+ {
+ SegmentedZeroCopyOutputStream output_stream(segments);
+ internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
+ int start = 0;
+ for (int j = 0; j < input_data.length() - 1; ++j) {
+ if (input_pattern & (1 << j)) {
+ byte_sink.Append(&input_data[start], j - start + 1);
+ start = j + 1;
+ }
+ }
+ byte_sink.Append(&input_data[start], input_data.length() - start);
+ }
+ EXPECT_EQ(input_data, string(buffer, input_data.length()));
+ EXPECT_EQ(0, buffer[input_data.length()]);
+ }
+
+ // Write 11 bytes through the ByteSink. The extra byte will just
+ // be ignored.
+ input_data = "0123456789A";
+ for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
+ input_pattern += kSkippedPatternCount) {
+ memset(buffer, 0, sizeof(buffer));
+ {
+ SegmentedZeroCopyOutputStream output_stream(segments);
+ internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
+ int start = 0;
+ for (int j = 0; j < input_data.length() - 1; ++j) {
+ if (input_pattern & (1 << j)) {
+ byte_sink.Append(&input_data[start], j - start + 1);
+ start = j + 1;
+ }
+ }
+ byte_sink.Append(&input_data[start], input_data.length() - start);
+ }
+ EXPECT_EQ(input_data.substr(0, kOutputBufferLength),
+ string(buffer, kOutputBufferLength));
+ }
+ }
+}
+
+} // namespace
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
new file mode 100644
index 00000000..057b414a
--- /dev/null
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -0,0 +1,1629 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: jschorr@google.com (Joseph Schorr)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file defines static methods and classes for comparing Protocol
+// Messages (see //google/protobuf/util/message_differencer.h for more
+// information).
+
+#include <google/protobuf/util/message_differencer.h>
+
+#include <algorithm>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <utility>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/any.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/util/field_comparator.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+
+namespace util {
+
+// When comparing a repeated field as map, MultipleFieldMapKeyComparator can
+// be used to specify multiple fields as key for key comparison.
+// Two elements of a repeated field will be regarded as having the same key
+// iff they have the same value for every specified key field.
+// Note that you can also specify only one field as key.
+class MessageDifferencer::MultipleFieldsMapKeyComparator
+ : public MessageDifferencer::MapKeyComparator {
+ public:
+ MultipleFieldsMapKeyComparator(
+ MessageDifferencer* message_differencer,
+ const vector<vector<const FieldDescriptor*> >& key_field_paths)
+ : message_differencer_(message_differencer),
+ key_field_paths_(key_field_paths) {
+ GOOGLE_CHECK(!key_field_paths_.empty());
+ for (int i = 0; i < key_field_paths_.size(); ++i) {
+ GOOGLE_CHECK(!key_field_paths_[i].empty());
+ }
+ }
+ MultipleFieldsMapKeyComparator(
+ MessageDifferencer* message_differencer,
+ const FieldDescriptor* key)
+ : message_differencer_(message_differencer) {
+ vector<const FieldDescriptor*> key_field_path;
+ key_field_path.push_back(key);
+ key_field_paths_.push_back(key_field_path);
+ }
+ virtual bool IsMatch(
+ const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& parent_fields) const {
+ for (int i = 0; i < key_field_paths_.size(); ++i) {
+ if (!IsMatchInternal(message1, message2, parent_fields,
+ key_field_paths_[i], 0)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ private:
+ bool IsMatchInternal(
+ const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& parent_fields,
+ const vector<const FieldDescriptor*>& key_field_path,
+ int path_index) const {
+ const FieldDescriptor* field = key_field_path[path_index];
+ vector<SpecificField> current_parent_fields(parent_fields);
+ if (path_index == key_field_path.size() - 1) {
+ if (field->is_repeated()) {
+ if (!message_differencer_->CompareRepeatedField(
+ message1, message2, field, &current_parent_fields)) {
+ return false;
+ }
+ } else {
+ if (!message_differencer_->CompareFieldValueUsingParentFields(
+ message1, message2, field, -1, -1, &current_parent_fields)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ const Reflection* reflection1 = message1.GetReflection();
+ const Reflection* reflection2 = message2.GetReflection();
+ bool has_field1 = reflection1->HasField(message1, field);
+ bool has_field2 = reflection2->HasField(message2, field);
+ if (!has_field1 && !has_field2) {
+ return true;
+ }
+ if (has_field1 != has_field2) {
+ return false;
+ }
+ SpecificField specific_field;
+ specific_field.field = field;
+ current_parent_fields.push_back(specific_field);
+ return IsMatchInternal(
+ reflection1->GetMessage(message1, field),
+ reflection2->GetMessage(message2, field),
+ current_parent_fields,
+ key_field_path,
+ path_index + 1);
+ }
+ }
+ MessageDifferencer* message_differencer_;
+ vector<vector<const FieldDescriptor*> > key_field_paths_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultipleFieldsMapKeyComparator);
+};
+
+bool MessageDifferencer::Equals(const Message& message1,
+ const Message& message2) {
+ MessageDifferencer differencer;
+
+ return differencer.Compare(message1, message2);
+}
+
+bool MessageDifferencer::Equivalent(const Message& message1,
+ const Message& message2) {
+ MessageDifferencer differencer;
+ differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT);
+
+ return differencer.Compare(message1, message2);
+}
+
+bool MessageDifferencer::ApproximatelyEquals(const Message& message1,
+ const Message& message2) {
+ MessageDifferencer differencer;
+ differencer.set_float_comparison(
+ MessageDifferencer::APPROXIMATE);
+
+ return differencer.Compare(message1, message2);
+}
+
+bool MessageDifferencer::ApproximatelyEquivalent(const Message& message1,
+ const Message& message2) {
+ MessageDifferencer differencer;
+ differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT);
+ differencer.set_float_comparison(MessageDifferencer::APPROXIMATE);
+
+ return differencer.Compare(message1, message2);
+}
+
+// ===========================================================================
+
+MessageDifferencer::MessageDifferencer()
+ : reporter_(NULL),
+ field_comparator_(NULL),
+ message_field_comparison_(EQUAL),
+ scope_(FULL),
+ repeated_field_comparison_(AS_LIST),
+ report_matches_(false),
+ output_string_(NULL) { }
+
+MessageDifferencer::~MessageDifferencer() {
+ for (int i = 0; i < owned_key_comparators_.size(); ++i) {
+ delete owned_key_comparators_[i];
+ }
+ for (int i = 0; i < ignore_criteria_.size(); ++i) {
+ delete ignore_criteria_[i];
+ }
+}
+
+void MessageDifferencer::set_field_comparator(FieldComparator* comparator) {
+ GOOGLE_CHECK(comparator) << "Field comparator can't be NULL.";
+ field_comparator_ = comparator;
+}
+
+void MessageDifferencer::set_message_field_comparison(
+ MessageFieldComparison comparison) {
+ message_field_comparison_ = comparison;
+}
+
+void MessageDifferencer::set_scope(Scope scope) {
+ scope_ = scope;
+}
+
+MessageDifferencer::Scope MessageDifferencer::scope() {
+ return scope_;
+}
+
+void MessageDifferencer::set_float_comparison(FloatComparison comparison) {
+ default_field_comparator_.set_float_comparison(
+ comparison == EXACT ?
+ DefaultFieldComparator::EXACT : DefaultFieldComparator::APPROXIMATE);
+}
+
+void MessageDifferencer::set_repeated_field_comparison(
+ RepeatedFieldComparison comparison) {
+ repeated_field_comparison_ = comparison;
+}
+
+void MessageDifferencer::TreatAsSet(const FieldDescriptor* field) {
+ GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
+ << field->full_name();
+ const MapKeyComparator* key_comparator = GetMapKeyComparator(field);
+ GOOGLE_CHECK(key_comparator == NULL)
+ << "Cannot treat this repeated field as both Map and Set for"
+ << " comparison. Field name is: " << field->full_name();
+ set_fields_.insert(field);
+}
+
+void MessageDifferencer::TreatAsMap(const FieldDescriptor* field,
+ const FieldDescriptor* key) {
+ GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
+ << field->full_name();
+ GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type())
+ << "Field has to be message type. Field name is: "
+ << field->full_name();
+ GOOGLE_CHECK(key->containing_type() == field->message_type())
+ << key->full_name()
+ << " must be a direct subfield within the repeated field "
+ << field->full_name() << ", not " << key->containing_type()->full_name();
+ GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end())
+ << "Cannot treat this repeated field as both Map and Set for "
+ << "comparison.";
+ MapKeyComparator* key_comparator =
+ new MultipleFieldsMapKeyComparator(this, key);
+ owned_key_comparators_.push_back(key_comparator);
+ map_field_key_comparator_[field] = key_comparator;
+}
+
+void MessageDifferencer::TreatAsMapWithMultipleFieldsAsKey(
+ const FieldDescriptor* field,
+ const vector<const FieldDescriptor*>& key_fields) {
+ vector<vector<const FieldDescriptor*> > key_field_paths;
+ for (int i = 0; i < key_fields.size(); ++i) {
+ vector<const FieldDescriptor*> key_field_path;
+ key_field_path.push_back(key_fields[i]);
+ key_field_paths.push_back(key_field_path);
+ }
+ TreatAsMapWithMultipleFieldPathsAsKey(field, key_field_paths);
+}
+
+void MessageDifferencer::TreatAsMapWithMultipleFieldPathsAsKey(
+ const FieldDescriptor* field,
+ const vector<vector<const FieldDescriptor*> >& key_field_paths) {
+ GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
+ << field->full_name();
+ GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type())
+ << "Field has to be message type. Field name is: "
+ << field->full_name();
+ for (int i = 0; i < key_field_paths.size(); ++i) {
+ const vector<const FieldDescriptor*>& key_field_path = key_field_paths[i];
+ for (int j = 0; j < key_field_path.size(); ++j) {
+ const FieldDescriptor* parent_field =
+ j == 0 ? field : key_field_path[j - 1];
+ const FieldDescriptor* child_field = key_field_path[j];
+ GOOGLE_CHECK(child_field->containing_type() == parent_field->message_type())
+ << child_field->full_name()
+ << " must be a direct subfield within the field: "
+ << parent_field->full_name();
+ if (j != 0) {
+ GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, parent_field->cpp_type())
+ << parent_field->full_name() << " has to be of type message.";
+ GOOGLE_CHECK(!parent_field->is_repeated())
+ << parent_field->full_name() << " cannot be a repeated field.";
+ }
+ }
+ }
+ GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end())
+ << "Cannot treat this repeated field as both Map and Set for "
+ << "comparison.";
+ MapKeyComparator* key_comparator =
+ new MultipleFieldsMapKeyComparator(this, key_field_paths);
+ owned_key_comparators_.push_back(key_comparator);
+ map_field_key_comparator_[field] = key_comparator;
+}
+
+void MessageDifferencer::TreatAsMapUsingKeyComparator(
+ const FieldDescriptor* field,
+ const MapKeyComparator* key_comparator) {
+ GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
+ << field->full_name();
+ GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type())
+ << "Field has to be message type. Field name is: "
+ << field->full_name();
+ GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end())
+ << "Cannot treat this repeated field as both Map and Set for "
+ << "comparison.";
+ map_field_key_comparator_[field] = key_comparator;
+}
+
+void MessageDifferencer::AddIgnoreCriteria(IgnoreCriteria* ignore_criteria) {
+ ignore_criteria_.push_back(ignore_criteria);
+}
+
+void MessageDifferencer::IgnoreField(const FieldDescriptor* field) {
+ ignored_fields_.insert(field);
+}
+
+void MessageDifferencer::SetFractionAndMargin(const FieldDescriptor* field,
+ double fraction, double margin) {
+ default_field_comparator_.SetFractionAndMargin(field, fraction, margin);
+}
+
+void MessageDifferencer::ReportDifferencesToString(string* output) {
+ GOOGLE_DCHECK(output) << "Specified output string was NULL";
+
+ output_string_ = output;
+ output_string_->clear();
+}
+
+void MessageDifferencer::ReportDifferencesTo(Reporter* reporter) {
+ // If an output string is set, clear it to prevent
+ // it superceding the specified reporter.
+ if (output_string_) {
+ output_string_ = NULL;
+ }
+
+ reporter_ = reporter;
+}
+
+bool MessageDifferencer::FieldBefore(const FieldDescriptor* field1,
+ const FieldDescriptor* field2) {
+ // Handle sentinel values (i.e. make sure NULLs are always ordered
+ // at the end of the list).
+ if (field1 == NULL) {
+ return false;
+ }
+
+ if (field2 == NULL) {
+ return true;
+ }
+
+ // Always order fields by their tag number
+ return (field1->number() < field2->number());
+}
+
+bool MessageDifferencer::Compare(const Message& message1,
+ const Message& message2) {
+ vector<SpecificField> parent_fields;
+
+ bool result = false;
+
+ // Setup the internal reporter if need be.
+ if (output_string_) {
+ io::StringOutputStream output_stream(output_string_);
+ StreamReporter reporter(&output_stream);
+ reporter_ = &reporter;
+ result = Compare(message1, message2, &parent_fields);
+ reporter_ = NULL;
+ } else {
+ result = Compare(message1, message2, &parent_fields);
+ }
+
+ return result;
+}
+
+bool MessageDifferencer::CompareWithFields(
+ const Message& message1,
+ const Message& message2,
+ const vector<const FieldDescriptor*>& message1_fields_arg,
+ const vector<const FieldDescriptor*>& message2_fields_arg) {
+ if (message1.GetDescriptor() != message2.GetDescriptor()) {
+ GOOGLE_LOG(DFATAL) << "Comparison between two messages with different "
+ << "descriptors.";
+ return false;
+ }
+
+ vector<SpecificField> parent_fields;
+
+ bool result = false;
+
+ vector<const FieldDescriptor*> message1_fields(message1_fields_arg);
+ vector<const FieldDescriptor*> message2_fields(message2_fields_arg);
+
+ std::sort(message1_fields.begin(), message1_fields.end(), FieldBefore);
+ std::sort(message2_fields.begin(), message2_fields.end(), FieldBefore);
+ // Append NULL sentinel values.
+ message1_fields.push_back(NULL);
+ message2_fields.push_back(NULL);
+
+ // Setup the internal reporter if need be.
+ if (output_string_) {
+ io::StringOutputStream output_stream(output_string_);
+ StreamReporter reporter(&output_stream);
+ reporter_ = &reporter;
+ result = CompareRequestedFieldsUsingSettings(
+ message1, message2, message1_fields, message2_fields, &parent_fields);
+ reporter_ = NULL;
+ } else {
+ result = CompareRequestedFieldsUsingSettings(
+ message1, message2, message1_fields, message2_fields, &parent_fields);
+ }
+
+ return result;
+}
+
+bool MessageDifferencer::Compare(
+ const Message& message1,
+ const Message& message2,
+ vector<SpecificField>* parent_fields) {
+ const Descriptor* descriptor1 = message1.GetDescriptor();
+ const Descriptor* descriptor2 = message2.GetDescriptor();
+ if (descriptor1 != descriptor2) {
+ GOOGLE_LOG(DFATAL) << "Comparison between two messages with different "
+ << "descriptors.";
+ return false;
+ }
+ // Expand google.protobuf.Any payload if possible.
+ if (descriptor1->full_name() == internal::kAnyFullTypeName) {
+ google::protobuf::scoped_ptr<Message> data1;
+ google::protobuf::scoped_ptr<Message> data2;
+ if (UnpackAny(message1, &data1) && UnpackAny(message2, &data2)) {
+ return Compare(*data1, *data2, parent_fields);
+ }
+ }
+ const Reflection* reflection1 = message1.GetReflection();
+ const Reflection* reflection2 = message2.GetReflection();
+
+ // Retrieve all the set fields, including extensions.
+ vector<const FieldDescriptor*> message1_fields;
+ vector<const FieldDescriptor*> message2_fields;
+
+ reflection1->ListFields(message1, &message1_fields);
+ reflection2->ListFields(message2, &message2_fields);
+
+ // Add sentinel values to deal with the
+ // case where the number of the fields in
+ // each list are different.
+ message1_fields.push_back(NULL);
+ message2_fields.push_back(NULL);
+
+ bool unknown_compare_result = true;
+ // Ignore unknown fields in EQUIVALENT mode
+ if (message_field_comparison_ != EQUIVALENT) {
+ const google::protobuf::UnknownFieldSet* unknown_field_set1 =
+ &reflection1->GetUnknownFields(message1);
+ const google::protobuf::UnknownFieldSet* unknown_field_set2 =
+ &reflection2->GetUnknownFields(message2);
+ if (!CompareUnknownFields(message1, message2,
+ *unknown_field_set1, *unknown_field_set2,
+ parent_fields)) {
+ if (reporter_ == NULL) {
+ return false;
+ };
+ unknown_compare_result = false;
+ }
+ }
+
+ return CompareRequestedFieldsUsingSettings(
+ message1, message2,
+ message1_fields, message2_fields,
+ parent_fields) && unknown_compare_result;
+}
+
+bool MessageDifferencer::CompareRequestedFieldsUsingSettings(
+ const Message& message1,
+ const Message& message2,
+ const vector<const FieldDescriptor*>& message1_fields,
+ const vector<const FieldDescriptor*>& message2_fields,
+ vector<SpecificField>* parent_fields) {
+ if (scope_ == FULL) {
+ if (message_field_comparison_ == EQUIVALENT) {
+ // We need to merge the field lists of both messages (i.e.
+ // we are merely checking for a difference in field values,
+ // rather than the addition or deletion of fields).
+ vector<const FieldDescriptor*> fields_union;
+ CombineFields(message1_fields, FULL, message2_fields, FULL,
+ &fields_union);
+ return CompareWithFieldsInternal(message1, message2, fields_union,
+ fields_union, parent_fields);
+ } else {
+ // Simple equality comparison, use the unaltered field lists.
+ return CompareWithFieldsInternal(message1, message2, message1_fields,
+ message2_fields, parent_fields);
+ }
+ } else {
+ if (message_field_comparison_ == EQUIVALENT) {
+ // We use the list of fields for message1 for both messages when
+ // comparing. This way, extra fields in message2 are ignored,
+ // and missing fields in message2 use their default value.
+ return CompareWithFieldsInternal(message1, message2, message1_fields,
+ message1_fields, parent_fields);
+ } else {
+ // We need to consider the full list of fields for message1
+ // but only the intersection for message2. This way, any fields
+ // only present in message2 will be ignored, but any fields only
+ // present in message1 will be marked as a difference.
+ vector<const FieldDescriptor*> fields_intersection;
+ CombineFields(message1_fields, PARTIAL, message2_fields, PARTIAL,
+ &fields_intersection);
+ return CompareWithFieldsInternal(message1, message2, message1_fields,
+ fields_intersection, parent_fields);
+ }
+ }
+}
+
+void MessageDifferencer::CombineFields(
+ const vector<const FieldDescriptor*>& fields1,
+ Scope fields1_scope,
+ const vector<const FieldDescriptor*>& fields2,
+ Scope fields2_scope,
+ vector<const FieldDescriptor*>* combined_fields) {
+
+ int index1 = 0;
+ int index2 = 0;
+
+ while (index1 < fields1.size() && index2 < fields2.size()) {
+ const FieldDescriptor* field1 = fields1[index1];
+ const FieldDescriptor* field2 = fields2[index2];
+
+ if (FieldBefore(field1, field2)) {
+ if (fields1_scope == FULL) {
+ combined_fields->push_back(fields1[index1]);
+ }
+ ++index1;
+ } else if (FieldBefore(field2, field1)) {
+ if (fields2_scope == FULL) {
+ combined_fields->push_back(fields2[index2]);
+ }
+ ++index2;
+ } else {
+ combined_fields->push_back(fields1[index1]);
+ ++index1;
+ ++index2;
+ }
+ }
+}
+
+bool MessageDifferencer::CompareWithFieldsInternal(
+ const Message& message1,
+ const Message& message2,
+ const vector<const FieldDescriptor*>& message1_fields,
+ const vector<const FieldDescriptor*>& message2_fields,
+ vector<SpecificField>* parent_fields) {
+ bool isDifferent = false;
+ int field_index1 = 0;
+ int field_index2 = 0;
+
+ const Reflection* reflection1 = message1.GetReflection();
+ const Reflection* reflection2 = message2.GetReflection();
+
+ while (true) {
+ const FieldDescriptor* field1 = message1_fields[field_index1];
+ const FieldDescriptor* field2 = message2_fields[field_index2];
+
+ // Once we have reached sentinel values, we are done the comparison.
+ if (field1 == NULL && field2 == NULL) {
+ break;
+ }
+
+ // Check for differences in the field itself.
+ if (FieldBefore(field1, field2)) {
+ // Field 1 is not in the field list for message 2.
+ if (IsIgnored(message1, message2, field1, *parent_fields)) {
+ // We are ignoring field1. Report the ignore and move on to
+ // the next field in message1_fields.
+ if (reporter_ != NULL) {
+ SpecificField specific_field;
+ specific_field.field = field1;
+
+ parent_fields->push_back(specific_field);
+ reporter_->ReportIgnored(message1, message2, *parent_fields);
+ parent_fields->pop_back();
+ }
+ ++field_index1;
+ continue;
+ }
+
+ if (reporter_ != NULL) {
+ int count = field1->is_repeated() ?
+ reflection1->FieldSize(message1, field1) : 1;
+
+ for (int i = 0; i < count; ++i) {
+ SpecificField specific_field;
+ specific_field.field = field1;
+ specific_field.index = field1->is_repeated() ? i : -1;
+
+ parent_fields->push_back(specific_field);
+ reporter_->ReportDeleted(message1, message2, *parent_fields);
+ parent_fields->pop_back();
+ }
+
+ isDifferent = true;
+ } else {
+ return false;
+ }
+
+ ++field_index1;
+ continue;
+ } else if (FieldBefore(field2, field1)) {
+ // Field 2 is not in the field list for message 1.
+ if (IsIgnored(message1, message2, field2, *parent_fields)) {
+ // We are ignoring field2. Report the ignore and move on to
+ // the next field in message2_fields.
+ if (reporter_ != NULL) {
+ SpecificField specific_field;
+ specific_field.field = field2;
+
+ parent_fields->push_back(specific_field);
+ reporter_->ReportIgnored(message1, message2, *parent_fields);
+ parent_fields->pop_back();
+ }
+ ++field_index2;
+ continue;
+ }
+
+ if (reporter_ != NULL) {
+ int count = field2->is_repeated() ?
+ reflection2->FieldSize(message2, field2) : 1;
+
+ for (int i = 0; i < count; ++i) {
+ SpecificField specific_field;
+ specific_field.field = field2;
+ specific_field.index = field2->is_repeated() ? i : -1;
+ specific_field.new_index = specific_field.index;
+
+ parent_fields->push_back(specific_field);
+ reporter_->ReportAdded(message1, message2, *parent_fields);
+ parent_fields->pop_back();
+ }
+
+ isDifferent = true;
+ } else {
+ return false;
+ }
+
+ ++field_index2;
+ continue;
+ }
+
+ // By this point, field1 and field2 are guarenteed to point to the same
+ // field, so we can now compare the values.
+ if (IsIgnored(message1, message2, field1, *parent_fields)) {
+ // Ignore this field. Report and move on.
+ if (reporter_ != NULL) {
+ SpecificField specific_field;
+ specific_field.field = field1;
+
+ parent_fields->push_back(specific_field);
+ reporter_->ReportIgnored(message1, message2, *parent_fields);
+ parent_fields->pop_back();
+ }
+
+ ++field_index1;
+ ++field_index2;
+ continue;
+ }
+
+ bool fieldDifferent = false;
+ if (field1->is_repeated()) {
+ fieldDifferent = !CompareRepeatedField(message1, message2, field1,
+ parent_fields);
+ if (fieldDifferent) {
+ if (reporter_ == NULL) return false;
+ isDifferent = true;
+ }
+ } else {
+ fieldDifferent = !CompareFieldValueUsingParentFields(
+ message1, message2, field1, -1, -1, parent_fields);
+
+ // If we have found differences, either report them or terminate if
+ // no reporter is present.
+ if (fieldDifferent && reporter_ == NULL) {
+ return false;
+ }
+
+ if (reporter_ != NULL) {
+ SpecificField specific_field;
+ specific_field.field = field1;
+ parent_fields->push_back(specific_field);
+ if (fieldDifferent) {
+ reporter_->ReportModified(message1, message2, *parent_fields);
+ isDifferent = true;
+ } else if (report_matches_) {
+ reporter_->ReportMatched(message1, message2, *parent_fields);
+ }
+ parent_fields->pop_back();
+ }
+ }
+ // Increment the field indicies.
+ ++field_index1;
+ ++field_index2;
+ }
+
+ return !isDifferent;
+}
+
+bool MessageDifferencer::IsMatch(const FieldDescriptor* repeated_field,
+ const MapKeyComparator* key_comparator,
+ const Message* message1,
+ const Message* message2,
+ const vector<SpecificField>& parent_fields,
+ int index1, int index2) {
+ vector<SpecificField> current_parent_fields(parent_fields);
+ if (repeated_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+ return CompareFieldValueUsingParentFields(
+ *message1, *message2, repeated_field, index1, index2,
+ &current_parent_fields);
+ }
+ // Back up the Reporter and output_string_. They will be reset in the
+ // following code.
+ Reporter* backup_reporter = reporter_;
+ string* output_string = output_string_;
+ reporter_ = NULL;
+ output_string_ = NULL;
+ bool match;
+
+ if (key_comparator == NULL) {
+ match = CompareFieldValueUsingParentFields(
+ *message1, *message2, repeated_field, index1, index2,
+ &current_parent_fields);
+ } else {
+ const Reflection* reflection1 = message1->GetReflection();
+ const Reflection* reflection2 = message2->GetReflection();
+ const Message& m1 =
+ reflection1->GetRepeatedMessage(*message1, repeated_field, index1);
+ const Message& m2 =
+ reflection2->GetRepeatedMessage(*message2, repeated_field, index2);
+ SpecificField specific_field;
+ specific_field.field = repeated_field;
+ current_parent_fields.push_back(specific_field);
+ match = key_comparator->IsMatch(m1, m2, current_parent_fields);
+ }
+
+ reporter_ = backup_reporter;
+ output_string_ = output_string;
+ return match;
+}
+
+bool MessageDifferencer::CompareRepeatedField(
+ const Message& message1,
+ const Message& message2,
+ const FieldDescriptor* repeated_field,
+ vector<SpecificField>* parent_fields) {
+ // the input FieldDescriptor is guaranteed to be repeated field.
+ const Reflection* reflection1 = message1.GetReflection();
+ const Reflection* reflection2 = message2.GetReflection();
+ const int count1 = reflection1->FieldSize(message1, repeated_field);
+ const int count2 = reflection2->FieldSize(message2, repeated_field);
+ const bool treated_as_subset = IsTreatedAsSubset(repeated_field);
+
+ // If the field is not treated as subset and no detailed reports is needed,
+ // we do a quick check on the number of the elements to avoid unnecessary
+ // comparison.
+ if (count1 != count2 && reporter_ == NULL && !treated_as_subset) {
+ return false;
+ }
+ // A match can never be found if message1 has more items than message2.
+ if (count1 > count2 && reporter_ == NULL) {
+ return false;
+ }
+
+ // These two list are used for store the index of the correspondent
+ // element in peer repeated field.
+ vector<int> match_list1;
+ vector<int> match_list2;
+
+ // Try to match indices of the repeated fields. Return false if match fails
+ // and there's no detailed report needed.
+ if (!MatchRepeatedFieldIndices(message1, message2, repeated_field,
+ *parent_fields, &match_list1, &match_list2) &&
+ reporter_ == NULL) {
+ return false;
+ }
+
+ bool fieldDifferent = false;
+ SpecificField specific_field;
+ specific_field.field = repeated_field;
+
+ // At this point, we have already matched pairs of fields (with the reporting
+ // to be done later). Now to check if the paired elements are different.
+ for (int i = 0; i < count1; i++) {
+ if (match_list1[i] == -1) continue;
+ specific_field.index = i;
+ specific_field.new_index = match_list1[i];
+
+ const bool result = CompareFieldValueUsingParentFields(
+ message1, message2, repeated_field, i, specific_field.new_index,
+ parent_fields);
+
+ // If we have found differences, either report them or terminate if
+ // no reporter is present. Note that ReportModified, ReportMoved, and
+ // ReportMatched are all mutually exclusive.
+ if (!result) {
+ if (reporter_ == NULL) return false;
+ parent_fields->push_back(specific_field);
+ reporter_->ReportModified(message1, message2, *parent_fields);
+ parent_fields->pop_back();
+ fieldDifferent = true;
+ } else if (reporter_ != NULL &&
+ specific_field.index != specific_field.new_index) {
+ parent_fields->push_back(specific_field);
+ reporter_->ReportMoved(message1, message2, *parent_fields);
+ parent_fields->pop_back();
+ } else if (report_matches_ && reporter_ != NULL) {
+ parent_fields->push_back(specific_field);
+ reporter_->ReportMatched(message1, message2, *parent_fields);
+ parent_fields->pop_back();
+ }
+ }
+
+ // Report any remaining additions or deletions.
+ for (int i = 0; i < count2; ++i) {
+ if (match_list2[i] != -1) continue;
+ if (!treated_as_subset) {
+ fieldDifferent = true;
+ }
+
+ if (reporter_ == NULL) continue;
+ specific_field.index = i;
+ specific_field.new_index = i;
+ parent_fields->push_back(specific_field);
+ reporter_->ReportAdded(message1, message2, *parent_fields);
+ parent_fields->pop_back();
+ }
+
+ for (int i = 0; i < count1; ++i) {
+ if (match_list1[i] != -1) continue;
+ specific_field.index = i;
+ parent_fields->push_back(specific_field);
+ reporter_->ReportDeleted(message1, message2, *parent_fields);
+ parent_fields->pop_back();
+ fieldDifferent = true;
+ }
+ return !fieldDifferent;
+}
+
+bool MessageDifferencer::CompareFieldValue(const Message& message1,
+ const Message& message2,
+ const FieldDescriptor* field,
+ int index1,
+ int index2) {
+ return CompareFieldValueUsingParentFields(message1, message2, field, index1,
+ index2, NULL);
+}
+
+bool MessageDifferencer::CompareFieldValueUsingParentFields(
+ const Message& message1, const Message& message2,
+ const FieldDescriptor* field, int index1, int index2,
+ vector<SpecificField>* parent_fields) {
+ FieldContext field_context(parent_fields);
+ FieldComparator::ComparisonResult result = GetFieldComparisonResult(
+ message1, message2, field, index1, index2, &field_context);
+
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ result == FieldComparator::RECURSE) {
+ // Get the nested messages and compare them using one of the Compare
+ // methods.
+ const Reflection* reflection1 = message1.GetReflection();
+ const Reflection* reflection2 = message2.GetReflection();
+ const Message& m1 = field->is_repeated() ?
+ reflection1->GetRepeatedMessage(message1, field, index1) :
+ reflection1->GetMessage(message1, field);
+ const Message& m2 = field->is_repeated() ?
+ reflection2->GetRepeatedMessage(message2, field, index2) :
+ reflection2->GetMessage(message2, field);
+
+ // parent_fields is used in calls to Reporter methods.
+ if (parent_fields != NULL) {
+ // Append currently compared field to the end of parent_fields.
+ SpecificField specific_field;
+ specific_field.field = field;
+ specific_field.index = index1;
+ specific_field.new_index = index2;
+ parent_fields->push_back(specific_field);
+ const bool compare_result = Compare(m1, m2, parent_fields);
+ parent_fields->pop_back();
+ return compare_result;
+ } else {
+ // Recreates parent_fields as if m1 and m2 had no parents.
+ return Compare(m1, m2);
+ }
+ } else {
+ return (result == FieldComparator::SAME);
+ }
+}
+
+bool MessageDifferencer::CheckPathChanged(
+ const vector<SpecificField>& field_path) {
+ for (int i = 0; i < field_path.size(); ++i) {
+ if (field_path[i].index != field_path[i].new_index) return true;
+ }
+ return false;
+}
+
+bool MessageDifferencer::IsTreatedAsSet(const FieldDescriptor* field) {
+ if (!field->is_repeated()) return false;
+ if (field->is_map()) return true;
+ if (repeated_field_comparison_ == AS_SET) return true;
+ return (set_fields_.find(field) != set_fields_.end());
+}
+
+bool MessageDifferencer::IsTreatedAsSubset(const FieldDescriptor* field) {
+ return scope_ == PARTIAL &&
+ (IsTreatedAsSet(field) || GetMapKeyComparator(field) != NULL);
+}
+
+bool MessageDifferencer::IsIgnored(
+ const Message& message1,
+ const Message& message2,
+ const FieldDescriptor* field,
+ const vector<SpecificField>& parent_fields) {
+ if (ignored_fields_.find(field) != ignored_fields_.end()) {
+ return true;
+ }
+ for (int i = 0; i < ignore_criteria_.size(); ++i) {
+ if (ignore_criteria_[i]->IsIgnored(message1, message2, field,
+ parent_fields)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+const MessageDifferencer::MapKeyComparator* MessageDifferencer
+ ::GetMapKeyComparator(const FieldDescriptor* field) {
+ if (!field->is_repeated()) return NULL;
+ if (map_field_key_comparator_.find(field) !=
+ map_field_key_comparator_.end()) {
+ return map_field_key_comparator_[field];
+ }
+ return NULL;
+}
+
+namespace {
+
+typedef pair<int, const UnknownField*> IndexUnknownFieldPair;
+
+struct UnknownFieldOrdering {
+ inline bool operator()(const IndexUnknownFieldPair& a,
+ const IndexUnknownFieldPair& b) const {
+ if (a.second->number() < b.second->number()) return true;
+ if (a.second->number() > b.second->number()) return false;
+ return a.second->type() < b.second->type();
+ }
+};
+
+} // namespace
+
+bool MessageDifferencer::UnpackAny(const Message& any,
+ google::protobuf::scoped_ptr<Message>* data) {
+ const Reflection* reflection = any.GetReflection();
+ const FieldDescriptor* type_url_field;
+ const FieldDescriptor* value_field;
+ if (!internal::GetAnyFieldDescriptors(any, &type_url_field, &value_field)) {
+ return false;
+ }
+ const string& type_url = reflection->GetString(any, type_url_field);
+ string full_type_name;
+ if (!internal::ParseAnyTypeUrl(type_url, &full_type_name)) {
+ return false;
+ }
+
+ const google::protobuf::Descriptor* desc =
+ any.GetDescriptor()->file()->pool()->FindMessageTypeByName(
+ full_type_name);
+ if (desc == NULL) {
+ GOOGLE_LOG(ERROR) << "Proto type '" << full_type_name << "' not found";
+ return false;
+ }
+
+ if (dynamic_message_factory_ == NULL) {
+ dynamic_message_factory_.reset(new DynamicMessageFactory());
+ }
+ data->reset(dynamic_message_factory_->GetPrototype(desc)->New());
+ string serialized_value = reflection->GetString(any, value_field);
+ if (!(*data)->ParseFromString(serialized_value)) {
+ GOOGLE_LOG(ERROR) << "Failed to parse value for " << full_type_name;
+ return false;
+ }
+ return true;
+}
+
+bool MessageDifferencer::CompareUnknownFields(
+ const Message& message1, const Message& message2,
+ const google::protobuf::UnknownFieldSet& unknown_field_set1,
+ const google::protobuf::UnknownFieldSet& unknown_field_set2,
+ vector<SpecificField>* parent_field) {
+ // Ignore unknown fields in EQUIVALENT mode.
+ if (message_field_comparison_ == EQUIVALENT) return true;
+
+ if (unknown_field_set1.empty() && unknown_field_set2.empty()) {
+ return true;
+ }
+
+ bool is_different = false;
+
+ // We first sort the unknown fields by field number and type (in other words,
+ // in tag order), making sure to preserve ordering of values with the same
+ // tag. This allows us to report only meaningful differences between the
+ // two sets -- that is, differing values for the same tag. We use
+ // IndexUnknownFieldPairs to keep track of the field's original index for
+ // reporting purposes.
+ vector<IndexUnknownFieldPair> fields1; // unknown_field_set1, sorted
+ vector<IndexUnknownFieldPair> fields2; // unknown_field_set2, sorted
+ fields1.reserve(unknown_field_set1.field_count());
+ fields2.reserve(unknown_field_set2.field_count());
+
+ for (int i = 0; i < unknown_field_set1.field_count(); i++) {
+ fields1.push_back(std::make_pair(i, &unknown_field_set1.field(i)));
+ }
+ for (int i = 0; i < unknown_field_set2.field_count(); i++) {
+ fields2.push_back(std::make_pair(i, &unknown_field_set2.field(i)));
+ }
+
+ UnknownFieldOrdering is_before;
+ std::stable_sort(fields1.begin(), fields1.end(), is_before);
+ std::stable_sort(fields2.begin(), fields2.end(), is_before);
+
+ // In order to fill in SpecificField::index, we have to keep track of how
+ // many values we've seen with the same field number and type.
+ // current_repeated points at the first field in this range, and
+ // current_repeated_start{1,2} are the indexes of the first field in the
+ // range within fields1 and fields2.
+ const UnknownField* current_repeated = NULL;
+ int current_repeated_start1 = 0;
+ int current_repeated_start2 = 0;
+
+ // Now that we have two sorted lists, we can detect fields which appear only
+ // in one list or the other by traversing them simultaneously.
+ int index1 = 0;
+ int index2 = 0;
+ while (index1 < fields1.size() || index2 < fields2.size()) {
+ enum { ADDITION, DELETION, MODIFICATION, COMPARE_GROUPS,
+ NO_CHANGE } change_type;
+
+ // focus_field is the field we're currently reporting on. (In the case
+ // of a modification, it's the field on the left side.)
+ const UnknownField* focus_field;
+ bool match = false;
+
+ if (index2 == fields2.size() ||
+ (index1 < fields1.size() &&
+ is_before(fields1[index1], fields2[index2]))) {
+ // fields1[index1] is not present in fields2.
+ change_type = DELETION;
+ focus_field = fields1[index1].second;
+ } else if (index1 == fields1.size() ||
+ is_before(fields2[index2], fields1[index1])) {
+ // fields2[index2] is not present in fields1.
+ if (scope_ == PARTIAL) {
+ // Ignore.
+ ++index2;
+ continue;
+ }
+ change_type = ADDITION;
+ focus_field = fields2[index2].second;
+ } else {
+ // Field type and number are the same. See if the values differ.
+ change_type = MODIFICATION;
+ focus_field = fields1[index1].second;
+
+ switch (focus_field->type()) {
+ case UnknownField::TYPE_VARINT:
+ match = fields1[index1].second->varint() ==
+ fields2[index2].second->varint();
+ break;
+ case UnknownField::TYPE_FIXED32:
+ match = fields1[index1].second->fixed32() ==
+ fields2[index2].second->fixed32();
+ break;
+ case UnknownField::TYPE_FIXED64:
+ match = fields1[index1].second->fixed64() ==
+ fields2[index2].second->fixed64();
+ break;
+ case UnknownField::TYPE_LENGTH_DELIMITED:
+ match = fields1[index1].second->length_delimited() ==
+ fields2[index2].second->length_delimited();
+ break;
+ case UnknownField::TYPE_GROUP:
+ // We must deal with this later, after building the SpecificField.
+ change_type = COMPARE_GROUPS;
+ break;
+ }
+ if (match && change_type != COMPARE_GROUPS) {
+ change_type = NO_CHANGE;
+ }
+ }
+
+ if (current_repeated == NULL ||
+ focus_field->number() != current_repeated->number() ||
+ focus_field->type() != current_repeated->type()) {
+ // We've started a new repeated field.
+ current_repeated = focus_field;
+ current_repeated_start1 = index1;
+ current_repeated_start2 = index2;
+ }
+
+ if (change_type == NO_CHANGE && reporter_ == NULL) {
+ // Fields were already compared and matched and we have no reporter.
+ ++index1;
+ ++index2;
+ continue;
+ }
+
+ if (change_type == ADDITION || change_type == DELETION ||
+ change_type == MODIFICATION) {
+ if (reporter_ == NULL) {
+ // We found a difference and we have no reproter.
+ return false;
+ }
+ is_different = true;
+ }
+
+ // Build the SpecificField. This is slightly complicated.
+ SpecificField specific_field;
+ specific_field.unknown_field_number = focus_field->number();
+ specific_field.unknown_field_type = focus_field->type();
+
+ specific_field.unknown_field_set1 = &unknown_field_set1;
+ specific_field.unknown_field_set2 = &unknown_field_set2;
+
+ if (change_type != ADDITION) {
+ specific_field.unknown_field_index1 = fields1[index1].first;
+ }
+ if (change_type != DELETION) {
+ specific_field.unknown_field_index2 = fields2[index2].first;
+ }
+
+ // Calculate the field index.
+ if (change_type == ADDITION) {
+ specific_field.index = index2 - current_repeated_start2;
+ specific_field.new_index = index2 - current_repeated_start2;
+ } else {
+ specific_field.index = index1 - current_repeated_start1;
+ specific_field.new_index = index2 - current_repeated_start2;
+ }
+
+ parent_field->push_back(specific_field);
+
+ switch (change_type) {
+ case ADDITION:
+ reporter_->ReportAdded(message1, message2, *parent_field);
+ ++index2;
+ break;
+ case DELETION:
+ reporter_->ReportDeleted(message1, message2, *parent_field);
+ ++index1;
+ break;
+ case MODIFICATION:
+ reporter_->ReportModified(message1, message2, *parent_field);
+ ++index1;
+ ++index2;
+ break;
+ case COMPARE_GROUPS:
+ if (!CompareUnknownFields(message1, message2,
+ fields1[index1].second->group(),
+ fields2[index2].second->group(),
+ parent_field)) {
+ if (reporter_ == NULL) return false;
+ is_different = true;
+ reporter_->ReportModified(message1, message2, *parent_field);
+ }
+ ++index1;
+ ++index2;
+ break;
+ case NO_CHANGE:
+ ++index1;
+ ++index2;
+ if (report_matches_) {
+ reporter_->ReportMatched(message1, message2, *parent_field);
+ }
+ }
+
+ parent_field->pop_back();
+ }
+
+ return !is_different;
+}
+
+namespace {
+
+// Find maximum bipartite matching using the argumenting path algorithm.
+class MaximumMatcher {
+ public:
+ typedef ResultCallback2<bool, int, int> NodeMatchCallback;
+ // MaximumMatcher takes ownership of the passed in callback and uses it to
+ // determine whether a node on the left side of the bipartial graph matches
+ // a node on the right side. count1 is the number of nodes on the left side
+ // of the graph and count2 to is the number of nodes on the right side.
+ // Every node is referred to using 0-based indices.
+ // If a maximum match is found, the result will be stored in match_list1 and
+ // match_list2. match_list1[i] == j means the i-th node on the left side is
+ // matched to the j-th node on the right side and match_list2[x] == y means
+ // the x-th node on the right side is matched to y-th node on the left side.
+ // match_list1[i] == -1 means the node is not matched. Same with match_list2.
+ MaximumMatcher(int count1, int count2, NodeMatchCallback* callback,
+ vector<int>* match_list1, vector<int>* match_list2);
+ // Find a maximum match and return the number of matched node pairs.
+ // If early_return is true, this method will return 0 immediately when it
+ // finds that not all nodes on the left side can be matched.
+ int FindMaximumMatch(bool early_return);
+ private:
+ // Determines whether the node on the left side of the bipartial graph
+ // matches the one on the right side.
+ bool Match(int left, int right);
+ // Find an argumenting path starting from the node v on the left side. If a
+ // path can be found, update match_list2_ to reflect the path and return
+ // true.
+ bool FindArgumentPathDFS(int v, vector<bool>* visited);
+
+ int count1_;
+ int count2_;
+ google::protobuf::scoped_ptr<NodeMatchCallback> match_callback_;
+ map<pair<int, int>, bool> cached_match_results_;
+ vector<int>* match_list1_;
+ vector<int>* match_list2_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MaximumMatcher);
+};
+
+MaximumMatcher::MaximumMatcher(int count1, int count2,
+ NodeMatchCallback* callback,
+ vector<int>* match_list1,
+ vector<int>* match_list2)
+ : count1_(count1), count2_(count2), match_callback_(callback),
+ match_list1_(match_list1), match_list2_(match_list2) {
+ match_list1_->assign(count1, -1);
+ match_list2_->assign(count2, -1);
+}
+
+int MaximumMatcher::FindMaximumMatch(bool early_return) {
+ int result = 0;
+ for (int i = 0; i < count1_; ++i) {
+ vector<bool> visited(count1_);
+ if (FindArgumentPathDFS(i, &visited)) {
+ ++result;
+ } else if (early_return) {
+ return 0;
+ }
+ }
+ // Backfill match_list1_ as we only filled match_list2_ when finding
+ // argumenting pathes.
+ for (int i = 0; i < count2_; ++i) {
+ if ((*match_list2_)[i] != -1) {
+ (*match_list1_)[(*match_list2_)[i]] = i;
+ }
+ }
+ return result;
+}
+
+bool MaximumMatcher::Match(int left, int right) {
+ pair<int, int> p(left, right);
+ map<pair<int, int>, bool>::iterator it = cached_match_results_.find(p);
+ if (it != cached_match_results_.end()) {
+ return it->second;
+ }
+ cached_match_results_[p] = match_callback_->Run(left, right);
+ return cached_match_results_[p];
+}
+
+bool MaximumMatcher::FindArgumentPathDFS(int v, vector<bool>* visited) {
+ (*visited)[v] = true;
+ // We try to match those un-matched nodes on the right side first. This is
+ // the step that the navie greedy matching algorithm uses. In the best cases
+ // where the greedy algorithm can find a maximum matching, we will always
+ // find a match in this step and the performance will be identical to the
+ // greedy algorithm.
+ for (int i = 0; i < count2_; ++i) {
+ int matched = (*match_list2_)[i];
+ if (matched == -1 && Match(v, i)) {
+ (*match_list2_)[i] = v;
+ return true;
+ }
+ }
+ // Then we try those already matched nodes and see if we can find an
+ // alternaive match for the node matched to them.
+ // The greedy algorithm will stop before this and fail to produce the
+ // correct result.
+ for (int i = 0; i < count2_; ++i) {
+ int matched = (*match_list2_)[i];
+ if (matched != -1 && Match(v, i)) {
+ if (!(*visited)[matched] && FindArgumentPathDFS(matched, visited)) {
+ (*match_list2_)[i] = v;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+bool MessageDifferencer::MatchRepeatedFieldIndices(
+ const Message& message1,
+ const Message& message2,
+ const FieldDescriptor* repeated_field,
+ const vector<SpecificField>& parent_fields,
+ vector<int>* match_list1,
+ vector<int>* match_list2) {
+ const int count1 =
+ message1.GetReflection()->FieldSize(message1, repeated_field);
+ const int count2 =
+ message2.GetReflection()->FieldSize(message2, repeated_field);
+ const MapKeyComparator* key_comparator = GetMapKeyComparator(repeated_field);
+
+ match_list1->assign(count1, -1);
+ match_list2->assign(count2, -1);
+
+ SpecificField specific_field;
+ specific_field.field = repeated_field;
+
+ bool success = true;
+ // Find potential match if this is a special repeated field.
+ if (key_comparator != NULL || IsTreatedAsSet(repeated_field)) {
+ if (scope_ == PARTIAL) {
+ // When partial matching is enabled, Compare(a, b) && Compare(a, c)
+ // doesn't neccessarily imply Compare(b, c). Therefore a naive greedy
+ // algorithm will fail to find a maximum matching.
+ // Here we use the argumenting path algorithm.
+ MaximumMatcher::NodeMatchCallback* callback = NewPermanentCallback(
+ this, &MessageDifferencer::IsMatch, repeated_field, key_comparator,
+ &message1, &message2, parent_fields);
+ MaximumMatcher matcher(count1, count2, callback, match_list1,
+ match_list2);
+ // If diff info is not needed, we should end the matching process as
+ // soon as possible if not all items can be matched.
+ bool early_return = (reporter_ == NULL);
+ int match_count = matcher.FindMaximumMatch(early_return);
+ if (match_count != count1 && reporter_ == NULL) return false;
+ success = success && (match_count == count1);
+ } else {
+ for (int i = 0; i < count1; ++i) {
+ // Indicates any matched elements for this repeated field.
+ bool match = false;
+
+ specific_field.index = i;
+ specific_field.new_index = i;
+
+ for (int j = 0; j < count2; j++) {
+ if (match_list2->at(j) != -1) continue;
+ specific_field.index = i;
+ specific_field.new_index = j;
+
+ match = IsMatch(repeated_field, key_comparator,
+ &message1, &message2, parent_fields, i, j);
+
+ if (match) {
+ match_list1->at(specific_field.index) = specific_field.new_index;
+ match_list2->at(specific_field.new_index) = specific_field.index;
+ break;
+ }
+ }
+ if (!match && reporter_ == NULL) return false;
+ success = success && match;
+ }
+ }
+ } else {
+ // If this field should be treated as list, just label the match_list.
+ for (int i = 0; i < count1 && i < count2; i++) {
+ match_list1->at(i) = i;
+ match_list2->at(i) = i;
+ }
+ }
+
+ return success;
+}
+
+FieldComparator::ComparisonResult MessageDifferencer::GetFieldComparisonResult(
+ const Message& message1, const Message& message2,
+ const FieldDescriptor* field, int index1, int index2,
+ const FieldContext* field_context) {
+ FieldComparator* comparator = field_comparator_ != NULL ?
+ field_comparator_ : &default_field_comparator_;
+ return comparator->Compare(message1, message2, field,
+ index1, index2, field_context);
+}
+
+// ===========================================================================
+
+MessageDifferencer::Reporter::Reporter() { }
+MessageDifferencer::Reporter::~Reporter() {}
+
+// ===========================================================================
+
+MessageDifferencer::MapKeyComparator::MapKeyComparator() {}
+MessageDifferencer::MapKeyComparator::~MapKeyComparator() {}
+
+// ===========================================================================
+
+MessageDifferencer::IgnoreCriteria::IgnoreCriteria() {}
+MessageDifferencer::IgnoreCriteria::~IgnoreCriteria() {}
+
+// ===========================================================================
+
+// Note that the printer's delimiter is not used, because if we are given a
+// printer, we don't know its delimiter.
+MessageDifferencer::StreamReporter::StreamReporter(
+ io::ZeroCopyOutputStream* output) : printer_(new io::Printer(output, '$')),
+ delete_printer_(true),
+ report_modified_aggregates_(false) { }
+
+MessageDifferencer::StreamReporter::StreamReporter(
+ io::Printer* printer) : printer_(printer),
+ delete_printer_(false),
+ report_modified_aggregates_(false) { }
+
+MessageDifferencer::StreamReporter::~StreamReporter() {
+ if (delete_printer_) delete printer_;
+}
+
+void MessageDifferencer::StreamReporter::PrintPath(
+ const vector<SpecificField>& field_path, bool left_side) {
+ for (int i = 0; i < field_path.size(); ++i) {
+ if (i > 0) {
+ printer_->Print(".");
+ }
+
+ SpecificField specific_field = field_path[i];
+
+ if (specific_field.field != NULL) {
+ if (specific_field.field->is_extension()) {
+ printer_->Print("($name$)", "name",
+ specific_field.field->full_name());
+ } else {
+ printer_->PrintRaw(specific_field.field->name());
+ }
+ } else {
+ printer_->PrintRaw(SimpleItoa(specific_field.unknown_field_number));
+ }
+ if (left_side && specific_field.index >= 0) {
+ printer_->Print("[$name$]", "name", SimpleItoa(specific_field.index));
+ }
+ if (!left_side && specific_field.new_index >= 0) {
+ printer_->Print("[$name$]", "name", SimpleItoa(specific_field.new_index));
+ }
+ }
+}
+
+void MessageDifferencer::
+StreamReporter::PrintValue(const Message& message,
+ const vector<SpecificField>& field_path,
+ bool left_side) {
+ const SpecificField& specific_field = field_path.back();
+ const FieldDescriptor* field = specific_field.field;
+ if (field != NULL) {
+ string output;
+ int index = left_side ? specific_field.index : specific_field.new_index;
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ const Reflection* reflection = message.GetReflection();
+ const Message& field_message = field->is_repeated() ?
+ reflection->GetRepeatedMessage(message, field, index) :
+ reflection->GetMessage(message, field);
+ output = field_message.ShortDebugString();
+ if (output.empty()) {
+ printer_->Print("{ }");
+ } else {
+ printer_->Print("{ $name$ }", "name", output);
+ }
+ } else {
+ TextFormat::PrintFieldValueToString(message, field, index, &output);
+ printer_->PrintRaw(output);
+ }
+ } else {
+ const UnknownFieldSet* unknown_fields =
+ (left_side ?
+ specific_field.unknown_field_set1 :
+ specific_field.unknown_field_set2);
+ const UnknownField* unknown_field = &unknown_fields->field(
+ left_side ?
+ specific_field.unknown_field_index1 :
+ specific_field.unknown_field_index2);
+ PrintUnknownFieldValue(unknown_field);
+ }
+}
+
+void MessageDifferencer::
+StreamReporter::PrintUnknownFieldValue(const UnknownField* unknown_field) {
+ GOOGLE_CHECK(unknown_field != NULL) << " Cannot print NULL unknown_field.";
+
+ string output;
+ switch (unknown_field->type()) {
+ case UnknownField::TYPE_VARINT:
+ output = SimpleItoa(unknown_field->varint());
+ break;
+ case UnknownField::TYPE_FIXED32:
+ output = StrCat("0x", strings::Hex(unknown_field->fixed32(),
+ strings::ZERO_PAD_8));
+ break;
+ case UnknownField::TYPE_FIXED64:
+ output = StrCat("0x", strings::Hex(unknown_field->fixed64(),
+ strings::ZERO_PAD_16));
+ break;
+ case UnknownField::TYPE_LENGTH_DELIMITED:
+ output = StringPrintf("\"%s\"",
+ CEscape(unknown_field->length_delimited()).c_str());
+ break;
+ case UnknownField::TYPE_GROUP:
+ // TODO(kenton): Print the contents of the group like we do for
+ // messages. Requires an equivalent of ShortDebugString() for
+ // UnknownFieldSet.
+ output = "{ ... }";
+ break;
+ }
+ printer_->PrintRaw(output);
+}
+
+void MessageDifferencer::StreamReporter::Print(const string& str) {
+ printer_->Print(str.c_str());
+}
+
+void MessageDifferencer::StreamReporter::ReportAdded(
+ const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& field_path) {
+ printer_->Print("added: ");
+ PrintPath(field_path, false);
+ printer_->Print(": ");
+ PrintValue(message2, field_path, false);
+ printer_->Print("\n"); // Print for newlines.
+}
+
+void MessageDifferencer::StreamReporter::ReportDeleted(
+ const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& field_path) {
+ printer_->Print("deleted: ");
+ PrintPath(field_path, true);
+ printer_->Print(": ");
+ PrintValue(message1, field_path, true);
+ printer_->Print("\n"); // Print for newlines
+}
+
+void MessageDifferencer::StreamReporter::ReportModified(
+ const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& field_path) {
+ if (!report_modified_aggregates_ && field_path.back().field == NULL) {
+ if (field_path.back().unknown_field_type == UnknownField::TYPE_GROUP) {
+ // Any changes to the subfields have already been printed.
+ return;
+ }
+ } else if (!report_modified_aggregates_) {
+ if (field_path.back().field->cpp_type() ==
+ FieldDescriptor::CPPTYPE_MESSAGE) {
+ // Any changes to the subfields have already been printed.
+ return;
+ }
+ }
+
+ printer_->Print("modified: ");
+ PrintPath(field_path, true);
+ if (CheckPathChanged(field_path)) {
+ printer_->Print(" -> ");
+ PrintPath(field_path, false);
+ }
+ printer_->Print(": ");
+ PrintValue(message1, field_path, true);
+ printer_->Print(" -> ");
+ PrintValue(message2, field_path, false);
+ printer_->Print("\n"); // Print for newlines.
+}
+
+void MessageDifferencer::StreamReporter::ReportMoved(
+ const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& field_path) {
+ printer_->Print("moved: ");
+ PrintPath(field_path, true);
+ printer_->Print(" -> ");
+ PrintPath(field_path, false);
+ printer_->Print(" : ");
+ PrintValue(message1, field_path, true);
+ printer_->Print("\n"); // Print for newlines.
+}
+
+void MessageDifferencer::StreamReporter::ReportMatched(
+ const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& field_path) {
+ printer_->Print("matched: ");
+ PrintPath(field_path, true);
+ if (CheckPathChanged(field_path)) {
+ printer_->Print(" -> ");
+ PrintPath(field_path, false);
+ }
+ printer_->Print(" : ");
+ PrintValue(message1, field_path, true);
+ printer_->Print("\n"); // Print for newlines.
+}
+
+void MessageDifferencer::StreamReporter::ReportIgnored(
+ const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& field_path) {
+ printer_->Print("ignored: ");
+ PrintPath(field_path, true);
+ if (CheckPathChanged(field_path)) {
+ printer_->Print(" -> ");
+ PrintPath(field_path, false);
+ }
+ printer_->Print("\n"); // Print for newlines.
+}
+
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h
new file mode 100644
index 00000000..e002a0f3
--- /dev/null
+++ b/src/google/protobuf/util/message_differencer.h
@@ -0,0 +1,808 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: jschorr@google.com (Joseph Schorr)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file defines static methods and classes for comparing Protocol
+// Messages.
+//
+// Aug. 2008: Added Unknown Fields Comparison for messages.
+// Aug. 2009: Added different options to compare repeated fields.
+// Apr. 2010: Moved field comparison to FieldComparator.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
+#define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+#include <google/protobuf/descriptor.h> // FieldDescriptor
+#include <google/protobuf/message.h> // Message
+#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/util/field_comparator.h>
+
+namespace google {
+namespace protobuf {
+
+class DynamicMessageFactory;
+class FieldDescriptor;
+
+namespace io {
+class ZeroCopyOutputStream;
+class Printer;
+}
+
+namespace util {
+
+class FieldContext; // declared below MessageDifferencer
+
+// A basic differencer that can be used to determine
+// the differences between two specified Protocol Messages. If any differences
+// are found, the Compare method will return false, and any differencer reporter
+// specified via ReportDifferencesTo will have its reporting methods called (see
+// below for implementation of the report). Based off of the original
+// ProtocolDifferencer implementation in //net/proto/protocol-differencer.h
+// (Thanks Todd!).
+//
+// MessageDifferencer REQUIRES that compared messages be the same type, defined
+// as messages that share the same descriptor. If not, the behavior of this
+// class is undefined.
+//
+// People disagree on what MessageDifferencer should do when asked to compare
+// messages with different descriptors. Some people think it should always
+// return false. Others expect it to try to look for similar fields and
+// compare them anyway -- especially if the descriptors happen to be identical.
+// If we chose either of these behaviors, some set of people would find it
+// surprising, and could end up writing code expecting the other behavior
+// without realizing their error. Therefore, we forbid that usage.
+//
+// This class is implemented based on the proto2 reflection. The performance
+// should be good enough for normal usages. However, for places where the
+// performance is extremely sensitive, there are several alternatives:
+// - Comparing serialized string
+// Downside: false negatives (there are messages that are the same but their
+// serialized strings are different).
+// - Equals code generator by compiler plugin (net/proto2/contrib/equals_plugin)
+// Downside: more generated code; maintenance overhead for the additional rule
+// (must be in sync with the original proto_library).
+//
+// Note on handling of google.protobuf.Any: MessageDifferencer automatically
+// unpacks Any::value into a Message and compares its individual fields.
+// Messages encoded in a repeated Any cannot be compared using TreatAsMap.
+//
+//
+// Note on thread-safety: MessageDifferencer is *not* thread-safe. You need to
+// guard it with a lock to use the same MessageDifferencer instance from
+// multiple threads. Note that it's fine to call static comparison methods
+// (like MessageDifferencer::Equals) concurrently.
+class LIBPROTOBUF_EXPORT MessageDifferencer {
+ public:
+ // Determines whether the supplied messages are equal. Equality is defined as
+ // all fields within the two messages being set to the same value. Primitive
+ // fields and strings are compared by value while embedded messages/groups
+ // are compared as if via a recursive call. Use IgnoreField() and Compare()
+ // if some fields should be ignored in the comparison.
+ //
+ // This method REQUIRES that the two messages have the same
+ // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
+ static bool Equals(const Message& message1, const Message& message2);
+
+ // Determines whether the supplied messages are equivalent. Equivalency is
+ // defined as all fields within the two messages having the same value. This
+ // differs from the Equals method above in that fields with default values
+ // are considered set to said value automatically. For details on how default
+ // values are defined for each field type, see http://shortn/_x2Gv6XFrWt.
+ // Also, Equivalent() ignores unknown fields. Use IgnoreField() and Compare()
+ // if some fields should be ignored in the comparison.
+ //
+ // This method REQUIRES that the two messages have the same
+ // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
+ static bool Equivalent(const Message& message1, const Message& message2);
+
+ // Determines whether the supplied messages are approximately equal.
+ // Approximate equality is defined as all fields within the two messages
+ // being approximately equal. Primitive (non-float) fields and strings are
+ // compared by value, floats are compared using MathUtil::AlmostEquals() and
+ // embedded messages/groups are compared as if via a recursive call. Use
+ // IgnoreField() and Compare() if some fields should be ignored in the
+ // comparison.
+ //
+ // This method REQUIRES that the two messages have the same
+ // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
+ static bool ApproximatelyEquals(const Message& message1,
+ const Message& message2);
+
+ // Determines whether the supplied messages are approximately equivalent.
+ // Approximate equivalency is defined as all fields within the two messages
+ // being approximately equivalent. As in
+ // MessageDifferencer::ApproximatelyEquals, primitive (non-float) fields and
+ // strings are compared by value, floats are compared using
+ // MathUtil::AlmostEquals() and embedded messages/groups are compared as if
+ // via a recursive call. However, fields with default values are considered
+ // set to said value, as per MessageDiffencer::Equivalent. Use IgnoreField()
+ // and Compare() if some fields should be ignored in the comparison.
+ //
+ // This method REQUIRES that the two messages have the same
+ // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
+ static bool ApproximatelyEquivalent(const Message& message1,
+ const Message& message2);
+
+ // Identifies an individual field in a message instance. Used for field_path,
+ // below.
+ struct SpecificField {
+ // For known fields, "field" is filled in and "unknown_field_number" is -1.
+ // For unknown fields, "field" is NULL, "unknown_field_number" is the field
+ // number, and "unknown_field_type" is its type.
+ const FieldDescriptor* field;
+ int unknown_field_number;
+ UnknownField::Type unknown_field_type;
+
+ // If this a repeated field, "index" is the index within it. For unknown
+ // fields, this is the index of the field among all unknown fields of the
+ // same field number and type.
+ int index;
+
+ // If "field" is a repeated field which is being treated as a map or
+ // a set (see TreatAsMap() and TreatAsSet(), below), new_index indicates
+ // the index the position to which the element has moved. This only
+ // applies to ReportMoved() and (in the case of TreatAsMap())
+ // ReportModified(). In all other cases, "new_index" will have the same
+ // value as "index".
+ int new_index;
+
+ // For unknown fields, these are the pointers to the UnknownFieldSet
+ // containing the unknown fields. In certain cases (e.g. proto1's
+ // MessageSet, or nested groups of unknown fields), these may differ from
+ // the messages' internal UnknownFieldSets.
+ const UnknownFieldSet* unknown_field_set1;
+ const UnknownFieldSet* unknown_field_set2;
+
+ // For unknown fields, these are the index of the field within the
+ // UnknownFieldSets. One or the other will be -1 when
+ // reporting an addition or deletion.
+ int unknown_field_index1;
+ int unknown_field_index2;
+
+ SpecificField()
+ : field(NULL),
+ unknown_field_number(-1),
+ index(-1),
+ new_index(-1),
+ unknown_field_set1(NULL),
+ unknown_field_set2(NULL),
+ unknown_field_index1(-1),
+ unknown_field_index2(-1) {}
+ };
+
+ // Abstract base class from which all MessageDifferencer
+ // reporters derive. The five Report* methods below will be called when
+ // a field has been added, deleted, modified, moved, or matched. The third
+ // argument is a vector of FieldDescriptor pointers which describes the chain
+ // of fields that was taken to find the current field. For example, for a
+ // field found in an embedded message, the vector will contain two
+ // FieldDescriptors. The first will be the field of the embedded message
+ // itself and the second will be the actual field in the embedded message
+ // that was added/deleted/modified.
+ class LIBPROTOBUF_EXPORT Reporter {
+ public:
+ Reporter();
+ virtual ~Reporter();
+
+ // Reports that a field has been added into Message2.
+ virtual void ReportAdded(
+ const Message& message1, const Message& message2,
+ const vector<SpecificField>& field_path) = 0;
+
+ // Reports that a field has been deleted from Message1.
+ virtual void ReportDeleted(
+ const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& field_path) = 0;
+
+ // Reports that the value of a field has been modified.
+ virtual void ReportModified(
+ const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& field_path) = 0;
+
+ // Reports that a repeated field has been moved to another location. This
+ // only applies when using TreatAsSet or TreatAsMap() -- see below. Also
+ // note that for any given field, ReportModified and ReportMoved are
+ // mutually exclusive. If a field has been both moved and modified, then
+ // only ReportModified will be called.
+ virtual void ReportMoved(
+ const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& field_path) { }
+
+ // Reports that two fields match. Useful for doing side-by-side diffs.
+ // This function is mutually exclusive with ReportModified and ReportMoved.
+ // Note that you must call set_report_matches(true) before calling Compare
+ // to make use of this function.
+ virtual void ReportMatched(
+ const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& field_path) { }
+
+ // Reports that two fields would have been compared, but the
+ // comparison has been skipped because the field was marked as
+ // 'ignored' using IgnoreField(). This function is mutually
+ // exclusive with all the other Report() functions.
+ //
+ // The contract of ReportIgnored is slightly different than the
+ // other Report() functions, in that |field_path.back().index| is
+ // always equal to -1, even if the last field is repeated. This is
+ // because while the other Report() functions indicate where in a
+ // repeated field the action (Addition, Deletion, etc...)
+ // happened, when a repeated field is 'ignored', the differencer
+ // simply calls ReportIgnored on the repeated field as a whole and
+ // moves on without looking at its individual elements.
+ //
+ // Furthermore, ReportIgnored() does not indicate whether the
+ // fields were in fact equal or not, as Compare() does not inspect
+ // these fields at all. It is up to the Reporter to decide whether
+ // the fields are equal or not (perhaps with a second call to
+ // Compare()), if it cares.
+ virtual void ReportIgnored(
+ const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& field_path) { }
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reporter);
+ };
+
+ // MapKeyComparator is used to determine if two elements have the same key
+ // when comparing elements of a repeated field as a map.
+ class LIBPROTOBUF_EXPORT MapKeyComparator {
+ public:
+ MapKeyComparator();
+ virtual ~MapKeyComparator();
+
+ virtual bool IsMatch(const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& parent_fields) const {
+ GOOGLE_CHECK(false) << "IsMatch() is not implemented.";
+ return false;
+ }
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapKeyComparator);
+ };
+
+ // Abstract base class from which all IgnoreCriteria derive.
+ // By adding IgnoreCriteria more complex ignore logic can be implemented.
+ // IgnoreCriteria are registed with AddIgnoreCriteria. For each compared
+ // field IsIgnored is called on each added IgnoreCriteria until one returns
+ // true or all return false.
+ // IsIgnored is called for fields where at least one side has a value.
+ class LIBPROTOBUF_EXPORT IgnoreCriteria {
+ public:
+ IgnoreCriteria();
+ virtual ~IgnoreCriteria();
+
+ // Returns true if the field should be ignored.
+ virtual bool IsIgnored(
+ const Message& message1,
+ const Message& message2,
+ const FieldDescriptor* field,
+ const vector<SpecificField>& parent_fields) = 0;
+ };
+
+ // To add a Reporter, construct default here, then use ReportDifferencesTo or
+ // ReportDifferencesToString.
+ explicit MessageDifferencer();
+
+ ~MessageDifferencer();
+
+ enum MessageFieldComparison {
+ EQUAL, // Fields must be present in both messages
+ // for the messages to be considered the same.
+ EQUIVALENT, // Fields with default values are considered set
+ // for comparison purposes even if not explicitly
+ // set in the messages themselves. Unknown fields
+ // are ignored.
+ };
+
+ enum Scope {
+ FULL, // All fields of both messages are considered in the comparison.
+ PARTIAL // Only fields present in the first message are considered; fields
+ // set only in the second message will be skipped during
+ // comparison.
+ };
+
+ // DEPRECATED. Use FieldComparator::FloatComparison instead.
+ enum FloatComparison {
+ EXACT, // Floats and doubles are compared exactly.
+ APPROXIMATE // Floats and doubles are compared using the
+ // MathUtil::AlmostEquals method.
+ };
+
+ enum RepeatedFieldComparison {
+ AS_LIST, // Repeated fields are compared in order. Differing values at
+ // the same index are reported using ReportModified(). If the
+ // repeated fields have different numbers of elements, the
+ // unpaired elements are reported using ReportAdded() or
+ // ReportDeleted().
+ AS_SET, // Treat all the repeated fields as sets by default.
+ // See TreatAsSet(), as below.
+ };
+
+ // The elements of the given repeated field will be treated as a set for
+ // diffing purposes, so different orderings of the same elements will be
+ // considered equal. Elements which are present on both sides of the
+ // comparison but which have changed position will be reported with
+ // ReportMoved(). Elements which only exist on one side or the other are
+ // reported with ReportAdded() and ReportDeleted() regardless of their
+ // positions. ReportModified() is never used for this repeated field. If
+ // the only differences between the compared messages is that some fields
+ // have been moved, then the comparison returns true.
+ //
+ // If the scope of comparison is set to PARTIAL, then in addition to what's
+ // above, extra values added to repeated fields of the second message will
+ // not cause the comparison to fail.
+ //
+ // Note that set comparison is currently O(k * n^2) (where n is the total
+ // number of elements, and k is the average size of each element). In theory
+ // it could be made O(n * k) with a more complex hashing implementation. Feel
+ // free to contribute one if the current implementation is too slow for you.
+ // If partial matching is also enabled, the time complexity will be O(k * n^2
+ // + n^3) in which n^3 is the time complexity of the maximum matching
+ // algorithm.
+ //
+ // REQUIRES: field->is_repeated()
+ void TreatAsSet(const FieldDescriptor* field);
+
+ // The elements of the given repeated field will be treated as a map for
+ // diffing purposes, with |key| being the map key. Thus, elements with the
+ // same key will be compared even if they do not appear at the same index.
+ // Differences are reported similarly to TreatAsSet(), except that
+ // ReportModified() is used to report elements with the same key but
+ // different values. Note that if an element is both moved and modified,
+ // only ReportModified() will be called. As with TreatAsSet, if the only
+ // differences between the compared messages is that some fields have been
+ // moved, then the comparison returns true. See TreatAsSet for notes on
+ // performance.
+ //
+ // REQUIRES: field->is_repeated()
+ // REQUIRES: field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
+ // REQUIRES: key->containing_type() == field->message_type()
+ void TreatAsMap(const FieldDescriptor* field, const FieldDescriptor* key);
+ // Same as TreatAsMap except that this method will use multiple fields as
+ // the key in comparison. All specified fields in 'key_fields' should be
+ // present in the compared elements. Two elements will be treated as having
+ // the same key iff they have the same value for every specified field. There
+ // are two steps in the comparison process. The first one is key matching.
+ // Every element from one message will be compared to every element from
+ // the other message. Only fields in 'key_fields' are compared in this step
+ // to decide if two elements have the same key. The second step is value
+ // comparison. Those pairs of elements with the same key (with equal value
+ // for every field in 'key_fields') will be compared in this step.
+ // Time complexity of the first step is O(s * m * n ^ 2) where s is the
+ // average size of the fields specified in 'key_fields', m is the number of
+ // fields in 'key_fields' and n is the number of elements. If partial
+ // matching is enabled, an extra O(n^3) will be incured by the maximum
+ // matching algorithm. The second step is O(k * n) where k is the average
+ // size of each element.
+ void TreatAsMapWithMultipleFieldsAsKey(
+ const FieldDescriptor* field,
+ const vector<const FieldDescriptor*>& key_fields);
+ // Same as TreatAsMapWithMultipleFieldsAsKey, except that each of the field
+ // do not necessarily need to be a direct subfield. Each element in
+ // key_field_paths indicate a path from the message being compared, listing
+ // successive subfield to reach the key field.
+ //
+ // REQUIRES:
+ // for key_field_path in key_field_paths:
+ // key_field_path[0]->containing_type() == field->message_type()
+ // for i in [0, key_field_path.size() - 1):
+ // key_field_path[i+1]->containing_type() ==
+ // key_field_path[i]->message_type()
+ // key_field_path[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
+ // !key_field_path[i]->is_repeated()
+ void TreatAsMapWithMultipleFieldPathsAsKey(
+ const FieldDescriptor* field,
+ const vector<vector<const FieldDescriptor*> >& key_field_paths);
+
+ // Uses a custom MapKeyComparator to determine if two elements have the same
+ // key when comparing a repeated field as a map.
+ // The caller is responsible to delete the key_comparator.
+ // This method varies from TreatAsMapWithMultipleFieldsAsKey only in the
+ // first key matching step. Rather than comparing some specified fields, it
+ // will invoke the IsMatch method of the given 'key_comparator' to decide if
+ // two elements have the same key.
+ void TreatAsMapUsingKeyComparator(
+ const FieldDescriptor* field,
+ const MapKeyComparator* key_comparator);
+
+ // Add a custom ignore criteria that is evaluated in addition to the
+ // ignored fields added with IgnoreField.
+ // Takes ownership of ignore_criteria.
+ void AddIgnoreCriteria(IgnoreCriteria* ignore_criteria);
+
+ // Indicates that any field with the given descriptor should be
+ // ignored for the purposes of comparing two messages. This applies
+ // to fields nested in the message structure as well as top level
+ // ones. When the MessageDifferencer encounters an ignored field,
+ // ReportIgnored is called on the reporter, if one is specified.
+ //
+ // The only place where the field's 'ignored' status is not applied is when
+ // it is being used as a key in a field passed to TreatAsMap or is one of
+ // the fields passed to TreatAsMapWithMultipleFieldsAsKey.
+ // In this case it is compared in key matching but after that it's ignored
+ // in value comparison.
+ void IgnoreField(const FieldDescriptor* field);
+
+ // Sets the field comparator used to determine differences between protocol
+ // buffer fields. By default it's set to a DefaultFieldComparator instance.
+ // MessageDifferencer doesn't take ownership over the passed object.
+ // Note that this method must be called before Compare for the comparator to
+ // be used.
+ void set_field_comparator(FieldComparator* comparator);
+
+ // DEPRECATED. Pass a DefaultFieldComparator instance instead.
+ // Sets the fraction and margin for the float comparison of a given field.
+ // Uses MathUtil::WithinFractionOrMargin to compare the values.
+ // NOTE: this method does nothing if differencer's field comparator has been
+ // set to a custom object.
+ //
+ // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or
+ // field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT
+ // REQUIRES: float_comparison_ == APPROXIMATE
+ void SetFractionAndMargin(const FieldDescriptor* field, double fraction,
+ double margin);
+
+ // Sets the type of comparison (as defined in the MessageFieldComparison
+ // enumeration above) that is used by this differencer when determining how
+ // to compare fields in messages.
+ void set_message_field_comparison(MessageFieldComparison comparison);
+
+ // Tells the differencer whether or not to report matches. This method must
+ // be called before Compare. The default for a new differencer is false.
+ void set_report_matches(bool report_matches) {
+ report_matches_ = report_matches;
+ }
+
+ // Sets the scope of the comparison (as defined in the Scope enumeration
+ // above) that is used by this differencer when determining which fields to
+ // compare between the messages.
+ void set_scope(Scope scope);
+
+ // Returns the current scope used by this differencer.
+ Scope scope();
+
+ // DEPRECATED. Pass a DefaultFieldComparator instance instead.
+ // Sets the type of comparison (as defined in the FloatComparison enumeration
+ // above) that is used by this differencer when comparing float (and double)
+ // fields in messages.
+ // NOTE: this method does nothing if differencer's field comparator has been
+ // set to a custom object.
+ void set_float_comparison(FloatComparison comparison);
+
+ // Sets the type of comparison for repeated field (as defined in the
+ // RepeatedFieldComparison enumeration above) that is used by this
+ // differencer when compare repeated fields in messages.
+ void set_repeated_field_comparison(RepeatedFieldComparison comparison);
+
+ // Compares the two specified messages, returning true if they are the same,
+ // false otherwise. If this method returns false, any changes between the
+ // two messages will be reported if a Reporter was specified via
+ // ReportDifferencesTo (see also ReportDifferencesToString).
+ //
+ // This method REQUIRES that the two messages have the same
+ // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
+ bool Compare(const Message& message1, const Message& message2);
+
+ // Same as above, except comparing only the list of fields specified by the
+ // two vectors of FieldDescriptors.
+ bool CompareWithFields(const Message& message1, const Message& message2,
+ const vector<const FieldDescriptor*>& message1_fields,
+ const vector<const FieldDescriptor*>& message2_fields);
+
+ // Automatically creates a reporter that will output the differences
+ // found (if any) to the specified output string pointer. Note that this
+ // method must be called before Compare.
+ void ReportDifferencesToString(string* output);
+
+ // Tells the MessageDifferencer to report differences via the specified
+ // reporter. Note that this method must be called before Compare for
+ // the reporter to be used. It is the responsibility of the caller to delete
+ // this object.
+ // If the provided pointer equals NULL, the MessageDifferencer stops reporting
+ // differences to any previously set reporters or output strings.
+ void ReportDifferencesTo(Reporter* reporter);
+
+ // An implementation of the MessageDifferencer Reporter that outputs
+ // any differences found in human-readable form to the supplied
+ // ZeroCopyOutputStream or Printer. If a printer is used, the delimiter
+ // *must* be '$'.
+ class LIBPROTOBUF_EXPORT StreamReporter : public Reporter {
+ public:
+ explicit StreamReporter(io::ZeroCopyOutputStream* output);
+ explicit StreamReporter(io::Printer* printer); // delimiter '$'
+ virtual ~StreamReporter();
+
+ // When set to true, the stream reporter will also output aggregates nodes
+ // (i.e. messages and groups) whose subfields have been modified. When
+ // false, will only report the individual subfields. Defaults to false.
+ void set_report_modified_aggregates(bool report) {
+ report_modified_aggregates_ = report;
+ }
+
+ // The following are implementations of the methods described above.
+ virtual void ReportAdded(const Message& message1, const Message& message2,
+ const vector<SpecificField>& field_path);
+
+ virtual void ReportDeleted(const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& field_path);
+
+ virtual void ReportModified(const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& field_path);
+
+ virtual void ReportMoved(const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& field_path);
+
+ virtual void ReportMatched(const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& field_path);
+
+ virtual void ReportIgnored(const Message& message1,
+ const Message& message2,
+ const vector<SpecificField>& field_path);
+
+ protected:
+ // Prints the specified path of fields to the buffer.
+ virtual void PrintPath(const vector<SpecificField>& field_path,
+ bool left_side);
+
+ // Prints the value of fields to the buffer. left_side is true if the
+ // given message is from the left side of the comparison, false if it
+ // was the right. This is relevant only to decide whether to follow
+ // unknown_field_index1 or unknown_field_index2 when an unknown field
+ // is encountered in field_path.
+ virtual void PrintValue(const Message& message,
+ const vector<SpecificField>& field_path,
+ bool left_side);
+
+ // Prints the specified path of unknown fields to the buffer.
+ virtual void PrintUnknownFieldValue(const UnknownField* unknown_field);
+
+ // Just print a string
+ void Print(const string& str);
+
+ private:
+ io::Printer* printer_;
+ bool delete_printer_;
+ bool report_modified_aggregates_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StreamReporter);
+ };
+
+ private:
+ // A MapKeyComparator to be used in TreatAsMapUsingKeyComparator.
+ // Implementation of this class needs to do field value comparison which
+ // relies on some private methods of MessageDifferencer. That's why this
+ // class is declared as a nested class of MessageDifferencer.
+ class MultipleFieldsMapKeyComparator;
+ // Returns true if field1's number() is less than field2's.
+ static bool FieldBefore(const FieldDescriptor* field1,
+ const FieldDescriptor* field2);
+
+ // Combine the two lists of fields into the combined_fields output vector.
+ // All fields present in both lists will always be included in the combined
+ // list. Fields only present in one of the lists will only appear in the
+ // combined list if the corresponding fields_scope option is set to FULL.
+ void CombineFields(const vector<const FieldDescriptor*>& fields1,
+ Scope fields1_scope,
+ const vector<const FieldDescriptor*>& fields2,
+ Scope fields2_scope,
+ vector<const FieldDescriptor*>* combined_fields);
+
+ // Internal version of the Compare method which performs the actual
+ // comparison. The parent_fields vector is a vector containing field
+ // descriptors of all fields accessed to get to this comparison operation
+ // (i.e. if the current message is an embedded message, the parent_fields
+ // vector will contain the field that has this embedded message).
+ bool Compare(const Message& message1, const Message& message2,
+ vector<SpecificField>* parent_fields);
+
+ // Compares all the unknown fields in two messages.
+ bool CompareUnknownFields(const Message& message1, const Message& message2,
+ const google::protobuf::UnknownFieldSet&,
+ const google::protobuf::UnknownFieldSet&,
+ vector<SpecificField>* parent_fields);
+
+ // Compares the specified messages for the requested field lists. The field
+ // lists are modified depending on comparison settings, and then passed to
+ // CompareWithFieldsInternal.
+ bool CompareRequestedFieldsUsingSettings(
+ const Message& message1, const Message& message2,
+ const vector<const FieldDescriptor*>& message1_fields,
+ const vector<const FieldDescriptor*>& message2_fields,
+ vector<SpecificField>* parent_fields);
+
+ // Compares the specified messages with the specified field lists.
+ bool CompareWithFieldsInternal(
+ const Message& message1, const Message& message2,
+ const vector<const FieldDescriptor*>& message1_fields,
+ const vector<const FieldDescriptor*>& message2_fields,
+ vector<SpecificField>* parent_fields);
+
+ // Compares the repeated fields, and report the error.
+ bool CompareRepeatedField(const Message& message1, const Message& message2,
+ const FieldDescriptor* field,
+ vector<SpecificField>* parent_fields);
+
+ // Shorthand for CompareFieldValueUsingParentFields with NULL parent_fields.
+ bool CompareFieldValue(const Message& message1,
+ const Message& message2,
+ const FieldDescriptor* field,
+ int index1,
+ int index2);
+
+ // Compares the specified field on the two messages, returning
+ // true if they are the same, false otherwise. For repeated fields,
+ // this method only compares the value in the specified index. This method
+ // uses Compare functions to recurse into submessages.
+ // The parent_fields vector is used in calls to a Reporter instance calls.
+ // It can be NULL, in which case the MessageDifferencer will create new
+ // list of parent messages if it needs to recursively compare the given field.
+ // To avoid confusing users you should not set it to NULL unless you modified
+ // Reporter to handle the change of parent_fields correctly.
+ bool CompareFieldValueUsingParentFields(const Message& message1,
+ const Message& message2,
+ const FieldDescriptor* field,
+ int index1,
+ int index2,
+ vector<SpecificField>* parent_fields);
+
+ // Compares the specified field on the two messages, returning comparison
+ // result, as returned by appropriate FieldComparator.
+ FieldComparator::ComparisonResult GetFieldComparisonResult(
+ const Message& message1, const Message& message2,
+ const FieldDescriptor* field, int index1, int index2,
+ const FieldContext* field_context);
+
+ // Check if the two elements in the repeated field are match to each other.
+ // if the key_comprator is NULL, this function returns true when the two
+ // elements are equal.
+ bool IsMatch(const FieldDescriptor* repeated_field,
+ const MapKeyComparator* key_comparator,
+ const Message* message1, const Message* message2,
+ const vector<SpecificField>& parent_fields,
+ int index1, int index2);
+
+ // Returns true when this repeated field has been configured to be treated
+ // as a set.
+ bool IsTreatedAsSet(const FieldDescriptor* field);
+
+ // Returns true when this repeated field is to be compared as a subset, ie.
+ // has been configured to be treated as a set or map and scope is set to
+ // PARTIAL.
+ bool IsTreatedAsSubset(const FieldDescriptor* field);
+
+ // Returns true if this field is to be ignored when this
+ // MessageDifferencer compares messages.
+ bool IsIgnored(
+ const Message& message1,
+ const Message& message2,
+ const FieldDescriptor* field,
+ const vector<SpecificField>& parent_fields);
+
+ // Returns MapKeyComparator* when this field has been configured to
+ // be treated as a map. If not, returns NULL.
+ const MapKeyComparator* GetMapKeyComparator(const FieldDescriptor* field);
+
+ // Attempts to match indices of a repeated field, so that the contained values
+ // match. Clears output vectors and sets their values to indices of paired
+ // messages, ie. if message1[0] matches message2[1], then match_list1[0] == 1
+ // and match_list2[1] == 0. The unmatched indices are indicated by -1.
+ // This method returns false if the match failed. However, it doesn't mean
+ // that the comparison succeeds when this method returns true (you need to
+ // double-check in this case).
+ bool MatchRepeatedFieldIndices(const Message& message1,
+ const Message& message2,
+ const FieldDescriptor* repeated_field,
+ const vector<SpecificField>& parent_fields,
+ vector<int>* match_list1,
+ vector<int>* match_list2);
+
+ // If "any" is of type google.protobuf.Any, extract its payload using
+ // DynamicMessageFactory and store in "data".
+ bool UnpackAny(const Message& any, google::protobuf::scoped_ptr<Message>* data);
+
+ // Checks if index is equal to new_index in all the specific fields.
+ static bool CheckPathChanged(const vector<SpecificField>& parent_fields);
+
+ // Defines a map between field descriptors and their MapKeyComparators.
+ // Used for repeated fields when they are configured as TreatAsMap.
+ typedef map<const FieldDescriptor*,
+ const MapKeyComparator*> FieldKeyComparatorMap;
+
+ // Defines a set to store field descriptors. Used for repeated fields when
+ // they are configured as TreatAsSet.
+ typedef set<const FieldDescriptor*> FieldSet;
+
+ Reporter* reporter_;
+ DefaultFieldComparator default_field_comparator_;
+ FieldComparator* field_comparator_;
+ MessageFieldComparison message_field_comparison_;
+ Scope scope_;
+ RepeatedFieldComparison repeated_field_comparison_;
+
+ FieldSet set_fields_;
+ // Keeps track of MapKeyComparators that are created within
+ // MessageDifferencer. These MapKeyComparators should be deleted
+ // before MessageDifferencer is destroyed.
+ // When TreatAsMap or TreatAsMapWithMultipleFieldsAsKey is called, we don't
+ // store the supplied FieldDescriptors directly. Instead, a new
+ // MapKeyComparator is created for comparison purpose.
+ vector<MapKeyComparator*> owned_key_comparators_;
+ FieldKeyComparatorMap map_field_key_comparator_;
+ vector<IgnoreCriteria*> ignore_criteria_;
+
+ FieldSet ignored_fields_;
+
+ bool compare_unknown_fields_;
+ bool report_matches_;
+
+ string* output_string_;
+
+ google::protobuf::scoped_ptr<DynamicMessageFactory> dynamic_message_factory_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageDifferencer);
+};
+
+// This class provides extra information to the FieldComparator::Compare
+// function.
+class LIBPROTOBUF_EXPORT FieldContext {
+ public:
+ explicit FieldContext(
+ vector<MessageDifferencer::SpecificField>* parent_fields)
+ : parent_fields_(parent_fields) {}
+
+ vector<MessageDifferencer::SpecificField>* parent_fields() const {
+ return parent_fields_;
+ }
+
+ private:
+ vector<MessageDifferencer::SpecificField>* parent_fields_;
+};
+
+}
+}
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
diff --git a/src/google/protobuf/util/message_differencer_unittest.cc b/src/google/protobuf/util/message_differencer_unittest.cc
new file mode 100755
index 00000000..bd19f695
--- /dev/null
+++ b/src/google/protobuf/util/message_differencer_unittest.cc
@@ -0,0 +1,3132 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: jschorr@google.com (Joseph Schorr)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// TODO(ksroka): Move some of these tests to field_comparator_test.cc.
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+
+#include <google/protobuf/util/field_comparator.h>
+#include <google/protobuf/util/message_differencer.h>
+#include <google/protobuf/util/message_differencer_unittest.pb.h>
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/any_test.pb.h>
+#include <google/protobuf/map_unittest.pb.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/map_test_util.h>
+#include <google/protobuf/test_util.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+
+const FieldDescriptor* GetFieldDescriptor(
+ const Message& message, const string& field_name) {
+ vector<string> field_path =
+ Split(field_name, ".", true);
+ const Descriptor* descriptor = message.GetDescriptor();
+ const FieldDescriptor* field = NULL;
+ for (int i = 0; i < field_path.size(); i++) {
+ field = descriptor->FindFieldByName(field_path[i]);
+ descriptor = field->message_type();
+ }
+ return field;
+}
+
+void ExpectEqualsWithDifferencer(util::MessageDifferencer* differencer,
+ const Message& msg1,
+ const Message& msg2) {
+ differencer->set_scope(util::MessageDifferencer::FULL);
+ EXPECT_TRUE(differencer->Compare(msg1, msg2));
+
+ differencer->set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_TRUE(differencer->Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicEqualityTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ // Compare
+ EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicInequalityTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ msg1.set_optional_int32(-1);
+
+ // Compare
+ EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldInequalityTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ msg1.add_repeated_int32(-1);
+
+ // Compare
+ EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, MapFieldEqualityTest) {
+ // Create the testing protos
+ unittest::TestMap msg1;
+ unittest::TestMap msg2;
+
+ MapTestUtil::MapReflectionTester tester(unittest::TestMap::descriptor());
+ tester.SetMapFieldsViaReflection(&msg1);
+ tester.SetMapFieldsViaReflection(&msg2);
+ tester.SwapMapsViaReflection(&msg1);
+
+ // Compare
+ EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicPartialEqualityTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, PartialEqualityTestExtraField) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ msg1.clear_optional_int32();
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, PartialEqualityTestSkipRequiredField) {
+ // Create the testing protos
+ unittest::TestRequired msg1;
+ unittest::TestRequired msg2;
+
+ msg1.set_a(401);
+ msg2.set_a(401);
+ msg2.set_b(402);
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicPartialInequalityTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ msg1.set_optional_int32(-1);
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, PartialInequalityMissingFieldTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ msg2.clear_optional_int32();
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldPartialInequalityTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ msg1.add_repeated_int32(-1);
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicEquivalencyTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ // Compare
+ EXPECT_TRUE(util::MessageDifferencer::Equivalent(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, EquivalencyNotEqualTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ msg1.clear_optional_int32();
+ msg2.set_optional_int32(0);
+
+ // Compare
+ EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+ EXPECT_TRUE(util::MessageDifferencer::Equivalent(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicInequivalencyTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ msg1.set_optional_int32(-1);
+
+ // Compare
+ EXPECT_FALSE(util::MessageDifferencer::Equivalent(msg1, msg2));
+}
+
+
+TEST(MessageDifferencerTest, BasicEquivalencyNonSetTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ // Compare
+ EXPECT_TRUE(util::MessageDifferencer::Equivalent(msg1, msg2));
+}
+
+
+TEST(MessageDifferencerTest, BasicInequivalencyNonSetTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ msg1.set_optional_int32(-1);
+
+ // Compare
+ EXPECT_FALSE(util::MessageDifferencer::Equivalent(msg1, msg2));
+}
+
+
+TEST(MessageDifferencerTest, BasicPartialEquivalencyTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.set_message_field_comparison(
+ util::MessageDifferencer::EQUIVALENT);
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, PartialEquivalencyNotEqualTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ msg1.set_optional_int32(0);
+ msg2.clear_optional_int32();
+
+ // Compare
+ EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+ util::MessageDifferencer differencer;
+ differencer.set_message_field_comparison(
+ util::MessageDifferencer::EQUIVALENT);
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, PartialEquivalencyTestExtraField) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ msg1.clear_optional_int32();
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.set_message_field_comparison(
+ util::MessageDifferencer::EQUIVALENT);
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, PartialEquivalencyTestSkipRequiredField) {
+ // Create the testing protos
+ unittest::TestRequired msg1;
+ unittest::TestRequired msg2;
+
+ msg1.set_a(401);
+ msg2.set_a(401);
+ msg2.set_b(402);
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.set_message_field_comparison(
+ util::MessageDifferencer::EQUIVALENT);
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicPartialInequivalencyTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ msg1.set_optional_int32(-1);
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.set_message_field_comparison(
+ util::MessageDifferencer::EQUIVALENT);
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicPartialEquivalencyNonSetTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.set_message_field_comparison(
+ util::MessageDifferencer::EQUIVALENT);
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicPartialInequivalencyNonSetTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ msg1.set_optional_int32(-1);
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.set_message_field_comparison(
+ util::MessageDifferencer::EQUIVALENT);
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, ApproximateEqualityTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ // Compare
+ EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, ApproximateModifiedEqualityTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ const float v1 = 2.300005f;
+ const float v2 = 2.300006f;
+ msg1.set_optional_float(v1);
+ msg2.set_optional_float(v2);
+
+ // Compare
+ ASSERT_NE(v1, v2) << "Should not be the same: " << v1 << ", " << v2;
+ ASSERT_FLOAT_EQ(v1, v2) << "Should be approx. equal: " << v1 << ", " << v2;
+ EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+ EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, ApproximateEquivalencyTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ // Compare
+ EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquivalent(msg1,
+ msg2));
+}
+
+TEST(MessageDifferencerTest, ApproximateModifiedEquivalencyTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ // Modify the approximateness requirement
+ const float v1 = 2.300005f;
+ const float v2 = 2.300006f;
+ msg1.set_optional_float(v1);
+ msg2.set_optional_float(v2);
+
+ // Compare
+ ASSERT_NE(v1, v2) << "Should not be the same: " << v1 << ", " << v2;
+ ASSERT_FLOAT_EQ(v1, v2) << "Should be approx. equal: " << v1 << ", " << v2;
+ EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+ EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquivalent(msg1,
+ msg2));
+
+ // Modify the equivalency requirement too
+ msg1.clear_optional_int32();
+ msg2.set_optional_int32(0);
+
+ // Compare. Now should only pass on ApproximatelyEquivalent
+ EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+ EXPECT_FALSE(util::MessageDifferencer::Equivalent(msg1, msg2));
+ EXPECT_FALSE(util::MessageDifferencer::ApproximatelyEquals(msg1, msg2));
+ EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquivalent(msg1,
+ msg2));
+}
+
+TEST(MessageDifferencerTest, ApproximateInequivalencyTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ // Should fail on equivalency
+ msg1.set_optional_int32(-1);
+ EXPECT_FALSE(util::MessageDifferencer::ApproximatelyEquivalent(msg1,
+ msg2));
+
+ // Make these fields the same again.
+ msg1.set_optional_int32(0);
+ msg2.set_optional_int32(0);
+ EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquivalent(msg1,
+ msg2));
+
+ // Should fail on approximate equality check
+ const float v1 = 2.3f;
+ const float v2 = 9.3f;
+ msg1.set_optional_float(v1);
+ msg2.set_optional_float(v2);
+ EXPECT_FALSE(util::MessageDifferencer::ApproximatelyEquivalent(msg1,
+ msg2));
+}
+
+TEST(MessageDifferencerTest, WithinFractionOrMarginFloatTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ // Should fail on approximate equality check
+ const float v1 = 100.0f;
+ const float v2 = 109.9f;
+ msg1.set_optional_float(v1);
+ msg2.set_optional_float(v2);
+
+ // Compare
+ util::MessageDifferencer differencer;
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+ const FieldDescriptor* fd =
+ msg1.GetDescriptor()->FindFieldByName("optional_float");
+
+ // Set float comparison to exact, margin and fraction value should not matter.
+ differencer.set_float_comparison(util::MessageDifferencer::EXACT);
+ // Set margin for float comparison.
+ differencer.SetFractionAndMargin(fd, 0.0, 10.0);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+ // Margin and fraction float comparison is activated when float comparison is
+ // set to approximate.
+ differencer.set_float_comparison(util::MessageDifferencer::APPROXIMATE);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+ // Test out float comparison with fraction.
+ differencer.SetFractionAndMargin(fd, 0.2, 0.0);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+ // Should fail since the fraction is smaller than error.
+ differencer.SetFractionAndMargin(fd, 0.01, 0.0);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+ // Should pass if either fraction or margin are satisfied.
+ differencer.SetFractionAndMargin(fd, 0.01, 10.0);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+ // Make sure that the margin and fraction only affects the field that it was
+ // set for.
+ msg1.set_default_float(v1);
+ msg2.set_default_float(v2);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+ msg1.set_default_float(v1);
+ msg2.set_default_float(v1);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, WithinFractionOrMarginDoubleTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ // Should fail on approximate equality check
+ const double v1 = 100.0;
+ const double v2 = 109.9;
+ msg1.set_optional_double(v1);
+ msg2.set_optional_double(v2);
+
+ // Compare
+ util::MessageDifferencer differencer;
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+ // Set comparison to exact, margin and fraction value should not matter.
+ differencer.set_float_comparison(util::MessageDifferencer::EXACT);
+ // Set margin for float comparison.
+ const FieldDescriptor* fd =
+ msg1.GetDescriptor()->FindFieldByName("optional_double");
+ differencer.SetFractionAndMargin(fd, 0.0, 10.0);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+ // Margin and fraction comparison is activated when float comparison is
+ // set to approximate.
+ differencer.set_float_comparison(util::MessageDifferencer::APPROXIMATE);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+ // Test out comparison with fraction.
+ differencer.SetFractionAndMargin(fd, 0.2, 0.0);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+ // Should fail since the fraction is smaller than error.
+ differencer.SetFractionAndMargin(fd, 0.01, 0.0);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+ // Should pass if either fraction or margin are satisfied.
+ differencer.SetFractionAndMargin(fd, 0.01, 10.0);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+ // Make sure that the margin and fraction only affects the field that it was
+ // set for.
+ msg1.set_default_double(v1);
+ msg2.set_default_double(v2);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+ msg1.set_default_double(v1);
+ msg2.set_default_double(v1);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, WithinDefaultFractionOrMarginDoubleTest) {
+ // Create the testing protos
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ // Should fail on approximate equality check
+ const double v1 = 100.0;
+ const double v2 = 109.9;
+ msg1.set_optional_double(v1);
+ msg2.set_optional_double(v2);
+
+ util::MessageDifferencer differencer;
+
+ // Compare
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+ // Set up a custom field comparitor, with a default fraction and margin for
+ // float and double comparison.
+ util::DefaultFieldComparator field_comparitor;
+ field_comparitor.SetDefaultFractionAndMargin(0.0, 10.0);
+ differencer.set_field_comparator(&field_comparitor);
+
+ // Set comparison to exact, margin and fraction value should not matter.
+ field_comparitor.set_float_comparison(util::DefaultFieldComparator::EXACT);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+ // Margin and fraction comparison is activated when float comparison is
+ // set to approximate.
+ field_comparitor.set_float_comparison(
+ util::DefaultFieldComparator::APPROXIMATE);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+ // Test out comparison with fraction.
+ field_comparitor.SetDefaultFractionAndMargin(0.2, 0.0);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+ // Should fail since the fraction is smaller than error.
+ field_comparitor.SetDefaultFractionAndMargin(0.01, 0.0);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+ // Should pass if either fraction or margin are satisfied.
+ field_comparitor.SetDefaultFractionAndMargin(0.01, 10.0);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+ // Make sure that the default margin and fraction affects all fields
+ msg1.set_default_double(v1);
+ msg2.set_default_double(v2);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicFieldOrderingsTest) {
+ // Create the testing protos
+ unittest::TestFieldOrderings msg1;
+ unittest::TestFieldOrderings msg2;
+
+ TestUtil::SetAllFieldsAndExtensions(&msg1);
+ TestUtil::SetAllFieldsAndExtensions(&msg2);
+
+ // Compare
+ EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+
+TEST(MessageDifferencerTest, BasicFieldOrderingInequalityTest) {
+ // Create the testing protos
+ unittest::TestFieldOrderings msg1;
+ unittest::TestFieldOrderings msg2;
+
+ TestUtil::SetAllFieldsAndExtensions(&msg1);
+ TestUtil::SetAllFieldsAndExtensions(&msg2);
+
+ msg1.set_my_float(15.00);
+ msg2.set_my_float(16.00);
+
+ // Compare
+ EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, BasicExtensionTest) {
+ // Create the testing protos
+ unittest::TestAllExtensions msg1;
+ unittest::TestAllExtensions msg2;
+
+ TestUtil::SetAllExtensions(&msg1);
+ TestUtil::SetAllExtensions(&msg2);
+
+ // Compare
+ EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+
+TEST(MessageDifferencerTest, BasicExtensionInequalityTest) {
+ // Create the testing protos
+ unittest::TestAllExtensions msg1;
+ unittest::TestAllExtensions msg2;
+
+ TestUtil::SetAllExtensions(&msg1);
+ TestUtil::SetAllExtensions(&msg2);
+
+ msg1.SetExtension(unittest::optional_int32_extension, 101);
+ msg2.SetExtension(unittest::optional_int32_extension, 102);
+
+ // Compare
+ EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, OneofTest) {
+ // Create the testing protos
+ unittest::TestOneof2 msg1;
+ unittest::TestOneof2 msg2;
+
+ TestUtil::SetOneof1(&msg1);
+ TestUtil::SetOneof1(&msg2);
+
+ // Compare
+ EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, OneofInequalityTest) {
+ // Create the testing protos
+ unittest::TestOneof2 msg1;
+ unittest::TestOneof2 msg2;
+
+ TestUtil::SetOneof1(&msg1);
+ TestUtil::SetOneof2(&msg2);
+
+ // Compare
+ EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, UnknownFieldPartialEqualTest) {
+ unittest::TestEmptyMessage empty1;
+ unittest::TestEmptyMessage empty2;
+
+ UnknownFieldSet* unknown1 = empty1.mutable_unknown_fields();
+ UnknownFieldSet* unknown2 = empty2.mutable_unknown_fields();
+
+ unknown1->AddVarint(243, 122);
+ unknown1->AddLengthDelimited(245, "abc");
+ unknown1->AddGroup(246)->AddFixed32(248, 1);
+ unknown1->mutable_field(2)->mutable_group()->AddFixed32(248, 2);
+
+ unknown2->AddVarint(243, 122);
+ unknown2->AddLengthDelimited(245, "abc");
+ unknown2->AddGroup(246)->AddFixed32(248, 1);
+ unknown2->mutable_field(2)->mutable_group()->AddFixed32(248, 2);
+
+ util::MessageDifferencer differencer;
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_TRUE(differencer.Compare(empty1, empty2));
+}
+
+TEST(MessageDifferencerTest, SpecifiedFieldsEqualityAllTest) {
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ vector<const FieldDescriptor*> fields1;
+ vector<const FieldDescriptor*> fields2;
+ msg1.GetReflection()->ListFields(msg1, &fields1);
+ msg2.GetReflection()->ListFields(msg2, &fields2);
+
+ util::MessageDifferencer differencer;
+ EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2));
+}
+
+TEST(MessageDifferencerTest, SpecifiedFieldsInequalityAllTest) {
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+
+ vector<const FieldDescriptor*> fields1;
+ vector<const FieldDescriptor*> fields2;
+ msg1.GetReflection()->ListFields(msg1, &fields1);
+ msg2.GetReflection()->ListFields(msg2, &fields2);
+
+ util::MessageDifferencer differencer;
+ EXPECT_FALSE(differencer.CompareWithFields(msg1, msg2, fields1, fields2));
+}
+
+TEST(MessageDifferencerTest, SpecifiedFieldsEmptyListAlwaysSucceeds) {
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+
+ vector<const FieldDescriptor*> empty_fields;
+
+ util::MessageDifferencer differencer;
+ EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2,
+ empty_fields, empty_fields));
+
+ TestUtil::SetAllFields(&msg2);
+ EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2,
+ empty_fields, empty_fields));
+}
+
+TEST(MessageDifferencerTest, SpecifiedFieldsCompareWithSelf) {
+ unittest::TestAllTypes msg1;
+ TestUtil::SetAllFields(&msg1);
+
+ vector<const FieldDescriptor*> fields;
+ msg1.GetReflection()->ListFields(msg1, &fields);
+
+ util::MessageDifferencer differencer;
+ EXPECT_TRUE(differencer.CompareWithFields(msg1, msg1, fields, fields));
+
+ {
+ // Compare with a subset of fields.
+ vector<const FieldDescriptor*> compare_fields;
+ for (int i = 0; i < fields.size(); ++i) {
+ if (i % 2 == 0) {
+ compare_fields.push_back(fields[i]);
+ }
+ }
+ EXPECT_TRUE(differencer.CompareWithFields(msg1, msg1,
+ compare_fields, compare_fields));
+ }
+ {
+ // Specify a different set of fields to compare, even though we're using the
+ // same message. This should fail, since we are explicitly saying that the
+ // set of fields are different.
+ vector<const FieldDescriptor*> compare_fields1;
+ vector<const FieldDescriptor*> compare_fields2;
+ for (int i = 0; i < fields.size(); ++i) {
+ if (i % 2 == 0) {
+ compare_fields1.push_back(fields[i]);
+ } else {
+ compare_fields2.push_back(fields[i]);
+ }
+ }
+ EXPECT_FALSE(differencer.CompareWithFields(
+ msg1, msg1, compare_fields1, compare_fields2));
+ }
+}
+
+TEST(MessageDifferencerTest, SpecifiedFieldsEqualityAllShuffledTest) {
+ // This is a public function, so make sure there are no assumptions about the
+ // list of fields. Randomly shuffle them to make sure that they are properly
+ // ordered for comparison.
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ vector<const FieldDescriptor*> fields1;
+ vector<const FieldDescriptor*> fields2;
+ msg1.GetReflection()->ListFields(msg1, &fields1);
+ msg2.GetReflection()->ListFields(msg2, &fields2);
+
+ std::random_shuffle(fields1.begin(), fields1.end());
+ std::random_shuffle(fields2.begin(), fields2.end());
+
+ util::MessageDifferencer differencer;
+ EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2));
+}
+
+TEST(MessageDifferencerTest, SpecifiedFieldsSubsetEqualityTest) {
+ // Specify a set of fields to compare. All the fields are equal.
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ vector<const FieldDescriptor*> fields1;
+ msg1.GetReflection()->ListFields(msg1, &fields1);
+
+ vector<const FieldDescriptor*> compare_fields;
+ // Only compare the field descriptors with even indices.
+ for (int i = 0; i < fields1.size(); ++i) {
+ if (i % 2 == 0) {
+ compare_fields.push_back(fields1[i]);
+ }
+ }
+
+ util::MessageDifferencer differencer;
+ EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2,
+ compare_fields, compare_fields));
+}
+
+TEST(MessageDifferencerTest,
+ SpecifiedFieldsSubsetIgnoresOtherFieldDifferencesTest) {
+ // Specify a set of fields to compare, but clear all the other fields in one
+ // of the messages. This should fail a regular compare, but CompareWithFields
+ // should succeed.
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ vector<const FieldDescriptor*> fields1;
+ const Reflection* reflection = msg1.GetReflection();
+ reflection->ListFields(msg1, &fields1);
+
+ vector<const FieldDescriptor*> compare_fields;
+ // Only compare the field descriptors with even indices.
+ for (int i = 0; i < fields1.size(); ++i) {
+ if (i % 2 == 0) {
+ compare_fields.push_back(fields1[i]);
+ } else {
+ reflection->ClearField(&msg2, fields1[i]);
+ }
+ }
+
+ util::MessageDifferencer differencer;
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+ EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2,
+ compare_fields, compare_fields));
+}
+
+TEST(MessageDifferencerTest, SpecifiedFieldsDetectsDifferencesTest) {
+ // Change all of the repeated fields in one of the messages, and use only
+ // those fields for comparison.
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+ TestUtil::ModifyRepeatedFields(&msg2);
+
+ vector<const FieldDescriptor*> fields1;
+ msg1.GetReflection()->ListFields(msg1, &fields1);
+
+ vector<const FieldDescriptor*> compare_fields;
+ // Only compare the repeated field descriptors.
+ for (int i = 0; i < fields1.size(); ++i) {
+ if (fields1[i]->is_repeated()) {
+ compare_fields.push_back(fields1[i]);
+ }
+ }
+
+ util::MessageDifferencer differencer;
+ EXPECT_FALSE(differencer.CompareWithFields(msg1, msg2,
+ compare_fields, compare_fields));
+}
+
+TEST(MessageDifferencerTest, SpecifiedFieldsEquivalenceAllTest) {
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+
+ TestUtil::SetAllFields(&msg1);
+ TestUtil::SetAllFields(&msg2);
+
+ vector<const FieldDescriptor*> fields1;
+ vector<const FieldDescriptor*> fields2;
+ msg1.GetReflection()->ListFields(msg1, &fields1);
+ msg2.GetReflection()->ListFields(msg2, &fields2);
+
+ util::MessageDifferencer differencer;
+ differencer.set_message_field_comparison(
+ util::MessageDifferencer::EQUIVALENT);
+ EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2));
+}
+
+TEST(MessageDifferencerTest,
+ SpecifiedFieldsEquivalenceIgnoresOtherFieldDifferencesTest) {
+ unittest::TestAllTypes msg1;
+ unittest::TestAllTypes msg2;
+ const Descriptor* desc = msg1.GetDescriptor();
+
+ const FieldDescriptor* optional_int32_desc =
+ desc->FindFieldByName("optional_int32");
+ const FieldDescriptor* optional_int64_desc =
+ desc->FindFieldByName("optional_int64");
+ const FieldDescriptor* default_int64_desc =
+ desc->FindFieldByName("default_int64");
+ ASSERT_TRUE(optional_int32_desc != NULL);
+ ASSERT_TRUE(optional_int64_desc != NULL);
+ ASSERT_TRUE(default_int64_desc != NULL);
+ msg1.set_optional_int32(0);
+ msg2.set_optional_int64(0);
+ msg1.set_default_int64(default_int64_desc->default_value_int64());
+
+ // Set a field to a non-default value so we know that field selection is
+ // actually doing something.
+ msg2.set_optional_uint64(23);
+
+ vector<const FieldDescriptor*> fields1;
+ vector<const FieldDescriptor*> fields2;
+ fields1.push_back(optional_int32_desc);
+ fields1.push_back(default_int64_desc);
+
+ fields2.push_back(optional_int64_desc);
+
+ util::MessageDifferencer differencer;
+ EXPECT_FALSE(differencer.CompareWithFields(msg1, msg2, fields1, fields2));
+ differencer.set_message_field_comparison(
+ util::MessageDifferencer::EQUIVALENT);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+ EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldSetTest_SetOfSet) {
+ // Create the testing protos
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+
+ protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+ item->add_ra(1); item->add_ra(2); item->add_ra(3);
+ item = msg1.add_item();
+ item->add_ra(5); item->add_ra(6);
+ item = msg1.add_item();
+ item->add_ra(1); item->add_ra(3);
+ item = msg1.add_item();
+ item->add_ra(6); item->add_ra(7); item->add_ra(8);
+
+ item = msg2.add_item();
+ item->add_ra(6); item->add_ra(5);
+ item = msg2.add_item();
+ item->add_ra(6); item->add_ra(8); item->add_ra(7);
+ item = msg2.add_item();
+ item->add_ra(1); item->add_ra(3);
+ item = msg2.add_item();
+ item->add_ra(3); item->add_ra(2); item->add_ra(1);
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.set_repeated_field_comparison(util::MessageDifferencer::AS_SET);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldSetTest_Combination) {
+ // Create the testing protos
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+ // Treat "item" as Map, with key = "a"
+ // Treat "item.ra" also as Set
+ // Treat "rv" as Set
+ // Treat "rw" as List
+ protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+ item->set_a(3);
+ item->add_ra(1); item->add_ra(2); item->add_ra(3);
+ item = msg1.add_item();
+ item->set_a(4);
+ item->add_ra(5); item->add_ra(6);
+ item = msg1.add_item();
+ item->set_a(1);
+ item->add_ra(1); item->add_ra(3);
+ item = msg1.add_item();
+ item->set_a(2);
+ item->add_ra(6); item->add_ra(7); item->add_ra(8);
+
+ item = msg2.add_item();
+ item->set_a(4);
+ item->add_ra(6); item->add_ra(5);
+ item = msg2.add_item();
+ item->set_a(2);
+ item->add_ra(6); item->add_ra(8); item->add_ra(7);
+ item = msg2.add_item();
+ item->set_a(1);
+ item->add_ra(1); item->add_ra(3);
+ item = msg2.add_item();
+ item->set_a(3);
+ item->add_ra(3); item->add_ra(2); item->add_ra(1);
+
+ msg1.add_rv(3);
+ msg1.add_rv(4);
+ msg1.add_rv(7);
+ msg1.add_rv(0);
+ msg2.add_rv(4);
+ msg2.add_rv(3);
+ msg2.add_rv(0);
+ msg2.add_rv(7);
+
+ msg1.add_rw("nothing"); msg2.add_rw("nothing");
+ msg1.add_rw("should"); msg2.add_rw("should");
+ msg1.add_rw("change"); msg2.add_rw("change");
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.TreatAsMap(msg1.GetDescriptor()->FindFieldByName("item"),
+ item->GetDescriptor()->FindFieldByName("a"));
+ differencer.TreatAsSet(msg1.GetDescriptor()->FindFieldByName("rv"));
+ differencer.TreatAsSet(item->GetDescriptor()->FindFieldByName("ra"));
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldMapTest_Partial) {
+ protobuf_unittest::TestDiffMessage msg1;
+ // message msg1 {
+ // item { a: 1; b: "11" }
+ // }
+ protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+ item->set_a(1);
+ item->set_b("11");
+
+ protobuf_unittest::TestDiffMessage msg2;
+ // message msg2 {
+ // item { a: 2; b: "22" }
+ // item { a: 1; b: "11" }
+ // }
+ item = msg2.add_item();
+ item->set_a(2);
+ item->set_b("22");
+ item = msg2.add_item();
+ item->set_a(1);
+ item->set_b("11");
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.TreatAsMap(GetFieldDescriptor(msg1, "item"),
+ GetFieldDescriptor(msg1, "item.a"));
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldSetTest_Duplicates) {
+ protobuf_unittest::TestDiffMessage a, b, c;
+ // message a: {
+ // rv: 0
+ // rv: 1
+ // rv: 0
+ // }
+ a.add_rv(0);
+ a.add_rv(1);
+ a.add_rv(0);
+ // message b: {
+ // rv: 0
+ // rv: 0
+ // rv: 1
+ // }
+ b.add_rv(0);
+ b.add_rv(0);
+ b.add_rv(1);
+ // message c: {
+ // rv: 0
+ // rv: 1
+ // }
+ c.add_rv(0);
+ c.add_rv(1);
+ util::MessageDifferencer differencer;
+ differencer.TreatAsSet(GetFieldDescriptor(a, "rv"));
+ EXPECT_TRUE(differencer.Compare(b, a));
+ EXPECT_FALSE(differencer.Compare(c, a));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldSetTest_PartialSimple) {
+ protobuf_unittest::TestDiffMessage a, b, c;
+ // message a: {
+ // rm { c: 1 }
+ // rm { c: 0 }
+ // }
+ a.add_rm()->set_c(1);
+ a.add_rm()->set_c(0);
+ // message b: {
+ // rm { c: 1 }
+ // rm {}
+ // }
+ b.add_rm()->set_c(1);
+ b.add_rm();
+ // message c: {
+ // rm {}
+ // rm { c: 1 }
+ // }
+ c.add_rm();
+ c.add_rm()->set_c(1);
+ util::MessageDifferencer differencer;
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ differencer.TreatAsSet(GetFieldDescriptor(a, "rm"));
+ EXPECT_TRUE(differencer.Compare(b, a));
+ EXPECT_TRUE(differencer.Compare(c, a));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldSetTest_Partial) {
+ protobuf_unittest::TestDiffMessage msg1, msg2;
+ // message msg1: {
+ // rm { a: 1 }
+ // rm { b: 2 }
+ // rm { c: 3 }
+ // }
+ msg1.add_rm()->set_a(1);
+ msg1.add_rm()->set_b(2);
+ msg1.add_rm()->set_c(3);
+ // message msg2: {
+ // rm { a: 1; c: 3 }
+ // rm { b: 2; c: 3 }
+ // rm { b: 2 }
+ // }
+ protobuf_unittest::TestField* field = msg2.add_rm();
+ field->set_a(1);
+ field->set_c(3);
+ field = msg2.add_rm();
+ field->set_b(2);
+ field->set_c(3);
+ field = msg2.add_rm();
+ field->set_b(2);
+
+ util::MessageDifferencer differencer;
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ differencer.TreatAsSet(GetFieldDescriptor(msg1, "rm"));
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldMapTest_MultipleFieldsAsKey) {
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+ // Treat "item" as Map, with key = ("a", "ra")
+ // Treat "item.ra" as Set
+ protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+ // key => value: (1, {2, 3}) => "a"
+ item->set_a(1);
+ item->add_ra(2);
+ item->add_ra(3);
+ item->set_b("a");
+ item = msg1.add_item();
+ // key => value: (2, {1, 3}) => "b"
+ item->set_a(2);
+ item->add_ra(1);
+ item->add_ra(3);
+ item->set_b("b");
+ item = msg1.add_item();
+ // key => value: (1, {1, 3}) => "c"
+ item->set_a(1);
+ item->add_ra(1);
+ item->add_ra(3);
+ item->set_b("c");
+
+ item = msg2.add_item();
+ // key => value: (1, {1, 3}) => "c"
+ item->set_a(1);
+ item->add_ra(3);
+ item->add_ra(1);
+ item->set_b("c");
+ item = msg2.add_item();
+ // key => value: (1, {2, 3}) => "a"
+ item->set_a(1);
+ item->add_ra(3);
+ item->add_ra(2);
+ item->set_b("a");
+ item = msg2.add_item();
+ // key => value: (2, {1, 3}) => "b"
+ item->set_a(2);
+ item->add_ra(3);
+ item->add_ra(1);
+ item->set_b("b");
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.TreatAsSet(GetFieldDescriptor(msg1, "item.ra"));
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+ vector<const FieldDescriptor*> key_fields;
+ key_fields.push_back(GetFieldDescriptor(msg1, "item.a"));
+ key_fields.push_back(GetFieldDescriptor(msg1, "item.ra"));
+ differencer.TreatAsMapWithMultipleFieldsAsKey(
+ GetFieldDescriptor(msg1, "item"), key_fields);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+ // Introduce some differences.
+ msg1.clear_item();
+ msg2.clear_item();
+ item = msg1.add_item();
+ item->set_a(4);
+ item->add_ra(5);
+ item->add_ra(6);
+ item->set_b("hello");
+ item = msg2.add_item();
+ item->set_a(4);
+ item->add_ra(6);
+ item->add_ra(5);
+ item->set_b("world");
+ string output;
+ differencer.ReportDifferencesToString(&output);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+ EXPECT_EQ(
+ "moved: item[0].ra[0] -> item[0].ra[1] : 5\n"
+ "moved: item[0].ra[1] -> item[0].ra[0] : 6\n"
+ "modified: item[0].b: \"hello\" -> \"world\"\n",
+ output);
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldMapTest_MultipleFieldPathsAsKey) {
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+ // Treat "item" as Map, with key = ("m.a", "m.rc")
+ // Treat "item.m.rc" as Set
+ protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+ // key => value: (1, {2, 3}) => "a"
+ item->mutable_m()->set_a(1);
+ item->mutable_m()->add_rc(2);
+ item->mutable_m()->add_rc(3);
+ item->set_b("a");
+ item = msg1.add_item();
+ // key => value: (2, {1, 3}) => "b"
+ item->mutable_m()->set_a(2);
+ item->mutable_m()->add_rc(1);
+ item->mutable_m()->add_rc(3);
+ item->set_b("b");
+ item = msg1.add_item();
+ // key => value: (1, {1, 3}) => "c"
+ item->mutable_m()->set_a(1);
+ item->mutable_m()->add_rc(1);
+ item->mutable_m()->add_rc(3);
+ item->set_b("c");
+
+ item = msg2.add_item();
+ // key => value: (1, {1, 3}) => "c"
+ item->mutable_m()->set_a(1);
+ item->mutable_m()->add_rc(3);
+ item->mutable_m()->add_rc(1);
+ item->set_b("c");
+ item = msg2.add_item();
+ // key => value: (1, {2, 3}) => "a"
+ item->mutable_m()->set_a(1);
+ item->mutable_m()->add_rc(3);
+ item->mutable_m()->add_rc(2);
+ item->set_b("a");
+ item = msg2.add_item();
+ // key => value: (2, {1, 3}) => "b"
+ item->mutable_m()->set_a(2);
+ item->mutable_m()->add_rc(3);
+ item->mutable_m()->add_rc(1);
+ item->set_b("b");
+
+ // Compare
+ util::MessageDifferencer differencer;
+ differencer.TreatAsSet(GetFieldDescriptor(msg1, "item.m.rc"));
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+ vector<vector<const FieldDescriptor*> > key_field_paths;
+ vector<const FieldDescriptor*> key_field_path1;
+ key_field_path1.push_back(GetFieldDescriptor(msg1, "item.m"));
+ key_field_path1.push_back(GetFieldDescriptor(msg1, "item.m.a"));
+ vector<const FieldDescriptor*> key_field_path2;
+ key_field_path2.push_back(GetFieldDescriptor(msg1, "item.m"));
+ key_field_path2.push_back(GetFieldDescriptor(msg1, "item.m.rc"));
+ key_field_paths.push_back(key_field_path1);
+ key_field_paths.push_back(key_field_path2);
+ differencer.TreatAsMapWithMultipleFieldPathsAsKey(
+ GetFieldDescriptor(msg1, "item"), key_field_paths);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+
+ // Introduce some differences.
+ msg1.clear_item();
+ msg2.clear_item();
+ item = msg1.add_item();
+ item->mutable_m()->set_a(4);
+ item->mutable_m()->add_rc(5);
+ item->mutable_m()->add_rc(6);
+ item->set_b("hello");
+ item = msg2.add_item();
+ item->mutable_m()->set_a(4);
+ item->mutable_m()->add_rc(6);
+ item->mutable_m()->add_rc(5);
+ item->set_b("world");
+ string output;
+ differencer.ReportDifferencesToString(&output);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+ EXPECT_EQ(
+ "modified: item[0].b: \"hello\" -> \"world\"\n"
+ "moved: item[0].m.rc[0] -> item[0].m.rc[1] : 5\n"
+ "moved: item[0].m.rc[1] -> item[0].m.rc[0] : 6\n",
+ output);
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldMapTest_IgnoredKeyFields) {
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+ // Treat "item" as Map, with key = ("a", "ra")
+ protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+ item->set_a(1);
+ item->add_ra(2);
+ item->set_b("hello");
+ item = msg2.add_item();
+ item->set_a(1);
+ item->add_ra(3);
+ item->set_b("world");
+ // Compare
+ util::MessageDifferencer differencer;
+ vector<const FieldDescriptor*> key_fields;
+ key_fields.push_back(GetFieldDescriptor(msg1, "item.a"));
+ key_fields.push_back(GetFieldDescriptor(msg1, "item.ra"));
+ differencer.TreatAsMapWithMultipleFieldsAsKey(
+ GetFieldDescriptor(msg1, "item"), key_fields);
+ string output;
+ differencer.ReportDifferencesToString(&output);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+ EXPECT_EQ(
+ "added: item[0]: { a: 1 ra: 3 b: \"world\" }\n"
+ "deleted: item[0]: { a: 1 ra: 2 b: \"hello\" }\n",
+ output);
+ // Ignored fields that are listed as parts of the key are still used
+ // in key comparison, but they're not used in value comparison.
+ differencer.IgnoreField(GetFieldDescriptor(msg1, "item.ra"));
+ output.clear();
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+ EXPECT_EQ(
+ "added: item[0]: { a: 1 ra: 3 b: \"world\" }\n"
+ "deleted: item[0]: { a: 1 ra: 2 b: \"hello\" }\n",
+ output);
+ // Ignoring a field in the key is different from treating the left fields
+ // as key. That is:
+ // (key = ("a", "ra") && ignore "ra") != (key = ("a") && ignore "ra")
+ util::MessageDifferencer differencer2;
+ differencer2.TreatAsMap(GetFieldDescriptor(msg1, "item"),
+ GetFieldDescriptor(msg1, "item.a"));
+ differencer2.IgnoreField(GetFieldDescriptor(msg1, "item.ra"));
+ output.clear();
+ differencer2.ReportDifferencesToString(&output);
+ EXPECT_FALSE(differencer2.Compare(msg1, msg2));
+ EXPECT_EQ(
+ "ignored: item[0].ra\n"
+ "modified: item[0].b: \"hello\" -> \"world\"\n",
+ output);
+}
+
+static const char* const kIgnoredFields[] = {"rm.b", "rm.m.b"};
+
+class TestIgnorer : public util::MessageDifferencer::IgnoreCriteria {
+ public:
+ bool IsIgnored(
+ const Message& message1, const Message& message2,
+ const FieldDescriptor* field,
+ const vector<util::MessageDifferencer::SpecificField>& parent_fields)
+ override {
+ string name = "";
+ for (int i = 0; i < parent_fields.size(); ++i) {
+ name += parent_fields[i].field->name() + ".";
+ }
+ name += field->name();
+ for (int i = 0; i < GOOGLE_ARRAYSIZE(kIgnoredFields); ++i) {
+ if (name.compare(kIgnoredFields[i]) == 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+TEST(MessageDifferencerTest, TreatRepeatedFieldAsSetWithIgnoredFields) {
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+ TextFormat::MergeFromString("rm { a: 11\n b: 12 }", &msg1);
+ TextFormat::MergeFromString("rm { a: 11\n b: 13 }", &msg2);
+ util::MessageDifferencer differ;
+ differ.TreatAsSet(GetFieldDescriptor(msg1, "rm"));
+ differ.AddIgnoreCriteria(new TestIgnorer);
+ EXPECT_TRUE(differ.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, TreatRepeatedFieldAsMapWithIgnoredKeyFields) {
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+ TextFormat::MergeFromString("rm { a: 11\n m { a: 12\n b: 13\n } }", &msg1);
+ TextFormat::MergeFromString("rm { a: 11\n m { a: 12\n b: 14\n } }", &msg2);
+ util::MessageDifferencer differ;
+ differ.TreatAsMap(GetFieldDescriptor(msg1, "rm"),
+ GetFieldDescriptor(msg1, "rm.m"));
+ differ.AddIgnoreCriteria(new TestIgnorer);
+ EXPECT_TRUE(differ.Compare(msg1, msg2));
+}
+
+// Takes the product of all elements of item.ra as the key for key comparison.
+class ValueProductMapKeyComparator
+ : public util::MessageDifferencer::MapKeyComparator {
+ public:
+ virtual bool IsMatch(const Message &message1,
+ const Message &message2) const {
+ const Reflection* reflection1 = message1.GetReflection();
+ const Reflection* reflection2 = message2.GetReflection();
+ // FieldDescriptor for item.ra
+ const FieldDescriptor* ra_field =
+ message1.GetDescriptor()->FindFieldByName("ra");
+ // Get the product of all elements in item.ra
+ int result1 = 1, result2 = 1;
+ for (int i = 0; i < reflection1->FieldSize(message1, ra_field); ++i) {
+ result1 *= reflection1->GetRepeatedInt32(message1, ra_field, i);
+ }
+ for (int i = 0; i < reflection2->FieldSize(message2, ra_field); ++i) {
+ result2 *= reflection2->GetRepeatedInt32(message2, ra_field, i);
+ }
+ return result1 == result2;
+ }
+};
+
+TEST(MessageDifferencerTest, RepeatedFieldMapTest_CustomMapKeyComparator) {
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+ // Treat "item" as Map, using custom key comparator to determine if two
+ // elements have the same key.
+ protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+ item->add_ra(6);
+ item->add_ra(35);
+ item->set_b("hello");
+ item = msg2.add_item();
+ item->add_ra(10);
+ item->add_ra(21);
+ item->set_b("hello");
+ util::MessageDifferencer differencer;
+ ValueProductMapKeyComparator key_comparator;
+ differencer.TreatAsMapUsingKeyComparator(
+ GetFieldDescriptor(msg1, "item"), &key_comparator);
+ string output;
+ differencer.ReportDifferencesToString(&output);
+ // Though the above two messages have different values for item.ra, they
+ // are regarded as having the same key because 6 * 35 == 10 * 21. That's
+ // how the key comparator determines if the two have the same key.
+ // However, in value comparison, all fields of the message are taken into
+ // consideration, so they are different because their item.ra fields have
+ // different values using normal value comparison.
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+ EXPECT_EQ(
+ "modified: item[0].ra[0]: 6 -> 10\n"
+ "modified: item[0].ra[1]: 35 -> 21\n",
+ output);
+ differencer.IgnoreField(GetFieldDescriptor(msg1, "item.ra"));
+ output.clear();
+ // item.ra is ignored in value comparison, so the two messages equal.
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+ EXPECT_EQ("ignored: item[0].ra\n", output);
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldSetTest_Subset) {
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+
+ msg1.add_rv(3);
+ msg1.add_rv(8);
+ msg1.add_rv(2);
+ msg2.add_rv(2);
+ msg2.add_rv(3);
+ msg2.add_rv(5);
+ msg2.add_rv(8);
+
+ util::MessageDifferencer differencer;
+
+ // Fail with only partial scope set.
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ differencer.set_repeated_field_comparison(util::MessageDifferencer::AS_LIST);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+ // Fail with only set-like comparison set.
+ differencer.set_scope(util::MessageDifferencer::FULL);
+ differencer.set_repeated_field_comparison(util::MessageDifferencer::AS_SET);
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+ // Succeed with scope and repeated field comparison set properly.
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ differencer.set_repeated_field_comparison(util::MessageDifferencer::AS_SET);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, IgnoreField_Single) {
+ protobuf_unittest::TestField msg1;
+ protobuf_unittest::TestField msg2;
+
+ msg1.set_c(3);
+ msg1.add_rc(1);
+
+ msg2.set_c(5);
+ msg2.add_rc(1);
+
+ util::MessageDifferencer differencer;
+ differencer.IgnoreField(GetFieldDescriptor(msg1, "c"));
+
+ ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_Repeated) {
+ protobuf_unittest::TestField msg1;
+ protobuf_unittest::TestField msg2;
+
+ msg1.set_c(3);
+ msg1.add_rc(1);
+ msg1.add_rc(2);
+
+ msg2.set_c(3);
+ msg2.add_rc(1);
+ msg2.add_rc(3);
+
+ util::MessageDifferencer differencer;
+ differencer.IgnoreField(GetFieldDescriptor(msg1, "rc"));
+
+ ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_Message) {
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+
+ protobuf_unittest::TestField* field;
+
+ field = msg1.add_rm();
+ field->set_c(3);
+
+ field = msg2.add_rm();
+ field->set_c(4);
+
+ util::MessageDifferencer differencer;
+ differencer.IgnoreField(GetFieldDescriptor(msg1, "rm"));
+
+ ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_Group) {
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+
+ protobuf_unittest::TestDiffMessage::Item* item;
+
+ item = msg1.add_item();
+ item->set_a(3);
+
+ item = msg2.add_item();
+ item->set_a(4);
+
+ util::MessageDifferencer differencer;
+ differencer.IgnoreField(GetFieldDescriptor(msg1, "item"));
+
+ ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_Missing) {
+ protobuf_unittest::TestField msg1;
+ protobuf_unittest::TestField msg2;
+
+ msg1.set_c(3);
+ msg1.add_rc(1);
+
+ msg2.add_rc(1);
+
+ util::MessageDifferencer differencer;
+ differencer.IgnoreField(GetFieldDescriptor(msg1, "c"));
+
+ ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+ ExpectEqualsWithDifferencer(&differencer, msg2, msg1);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_Multiple) {
+ protobuf_unittest::TestField msg1;
+ protobuf_unittest::TestField msg2;
+
+ msg1.set_c(3);
+ msg1.add_rc(1);
+ msg1.add_rc(2);
+
+ msg2.set_c(5);
+ msg2.add_rc(1);
+ msg2.add_rc(3);
+
+ const FieldDescriptor* c = GetFieldDescriptor(msg1, "c");
+ const FieldDescriptor* rc = GetFieldDescriptor(msg1, "rc");
+
+ { // Ignore c
+ util::MessageDifferencer differencer;
+ differencer.IgnoreField(c);
+
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+ }
+ { // Ignore rc
+ util::MessageDifferencer differencer;
+ differencer.IgnoreField(rc);
+
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+ }
+ { // Ignore both
+ util::MessageDifferencer differencer;
+ differencer.IgnoreField(c);
+ differencer.IgnoreField(rc);
+
+ ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+ }
+}
+
+TEST(MessageDifferencerTest, IgnoreField_NestedMessage) {
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+
+ protobuf_unittest::TestField* field;
+
+ field = msg1.add_rm();
+ field->set_c(3);
+ field->add_rc(1);
+
+ field = msg2.add_rm();
+ field->set_c(4);
+ field->add_rc(1);
+
+ util::MessageDifferencer differencer;
+ differencer.IgnoreField(GetFieldDescriptor(msg1, "rm.c"));
+
+ ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_NestedGroup) {
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+
+ protobuf_unittest::TestDiffMessage::Item* item;
+
+ item = msg1.add_item();
+ item->set_a(3);
+ item->set_b("foo");
+
+ item = msg2.add_item();
+ item->set_a(4);
+ item->set_b("foo");
+
+ util::MessageDifferencer differencer;
+ differencer.IgnoreField(GetFieldDescriptor(msg1, "item.a"));
+
+ ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_InsideSet) {
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+
+ protobuf_unittest::TestDiffMessage::Item* item;
+
+ item = msg1.add_item();
+ item->set_a(1);
+ item->set_b("foo");
+ item->add_ra(1);
+
+ item = msg1.add_item();
+ item->set_a(2);
+ item->set_b("bar");
+ item->add_ra(2);
+
+ item = msg2.add_item();
+ item->set_a(2);
+ item->set_b("bar");
+ item->add_ra(2);
+
+ item = msg2.add_item();
+ item->set_a(1);
+ item->set_b("baz");
+ item->add_ra(1);
+
+ const FieldDescriptor* item_desc = GetFieldDescriptor(msg1, "item");
+ const FieldDescriptor* b = GetFieldDescriptor(msg1, "item.b");
+
+ util::MessageDifferencer differencer;
+ differencer.IgnoreField(b);
+ differencer.TreatAsSet(item_desc);
+
+ ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_InsideMap) {
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+
+ protobuf_unittest::TestDiffMessage::Item* item;
+
+ item = msg1.add_item();
+ item->set_a(1);
+ item->set_b("foo");
+ item->add_ra(1);
+
+ item = msg1.add_item();
+ item->set_a(2);
+ item->set_b("bar");
+ item->add_ra(2);
+
+ item = msg2.add_item();
+ item->set_a(2);
+ item->set_b("bar");
+ item->add_ra(2);
+
+ item = msg2.add_item();
+ item->set_a(1);
+ item->set_b("baz");
+ item->add_ra(1);
+
+ const FieldDescriptor* item_desc = GetFieldDescriptor(msg1, "item");
+ const FieldDescriptor* a = GetFieldDescriptor(msg1, "item.a");
+ const FieldDescriptor* b = GetFieldDescriptor(msg1, "item.b");
+
+ util::MessageDifferencer differencer;
+ differencer.IgnoreField(b);
+ differencer.TreatAsMap(item_desc, a);
+
+ ExpectEqualsWithDifferencer(&differencer, msg1, msg2);
+}
+
+TEST(MessageDifferencerTest, IgnoreField_DoesNotIgnoreKey) {
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+
+ protobuf_unittest::TestDiffMessage::Item* item;
+
+ item = msg1.add_item();
+ item->set_a(1);
+ item->set_b("foo");
+ item->add_ra(1);
+
+ item = msg2.add_item();
+ item->set_a(2);
+ item->set_b("foo");
+ item->add_ra(1);
+
+ const FieldDescriptor* item_desc = GetFieldDescriptor(msg1, "item");
+ const FieldDescriptor* a = GetFieldDescriptor(msg1, "item.a");
+
+ util::MessageDifferencer differencer;
+ differencer.IgnoreField(a);
+ differencer.TreatAsMap(item_desc, a);
+
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, IgnoreField_TrumpsCompareWithFields) {
+ protobuf_unittest::TestField msg1;
+ protobuf_unittest::TestField msg2;
+
+ msg1.set_c(3);
+ msg1.add_rc(1);
+ msg1.add_rc(2);
+
+ msg2.set_c(3);
+ msg2.add_rc(1);
+ msg2.add_rc(3);
+
+ const FieldDescriptor* c = GetFieldDescriptor(msg1, "c");
+ const FieldDescriptor* rc = GetFieldDescriptor(msg1, "rc");
+
+ vector<const FieldDescriptor*> fields;
+ fields.push_back(c);
+ fields.push_back(rc);
+
+ util::MessageDifferencer differencer;
+ differencer.IgnoreField(rc);
+
+ differencer.set_scope(util::MessageDifferencer::FULL);
+ EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields, fields));
+
+ differencer.set_scope(util::MessageDifferencer::PARTIAL);
+ EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields, fields));
+}
+
+
+// Test class to save a copy of the last field_context.parent_fields() vector
+// passed to the comparison function.
+class ParentSavingFieldComparator : public util::FieldComparator {
+ public:
+ ParentSavingFieldComparator() {}
+
+ virtual ComparisonResult Compare(
+ const google::protobuf::Message& message_1,
+ const google::protobuf::Message& message_2,
+ const google::protobuf::FieldDescriptor* field,
+ int index_1, int index_2,
+ const google::protobuf::util::FieldContext* field_context) {
+ if (field_context)
+ parent_fields_ = *(field_context->parent_fields());
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ return RECURSE;
+ } else {
+ return SAME;
+ }
+ }
+
+ vector<google::protobuf::util::MessageDifferencer::SpecificField> parent_fields() {
+ return parent_fields_;
+ }
+
+ private:
+ vector<google::protobuf::util::MessageDifferencer::SpecificField> parent_fields_;
+};
+
+// Tests if MessageDifferencer sends the parent fields in the FieldContext
+// parameter.
+TEST(MessageDifferencerTest, FieldContextParentFieldsTest) {
+ protobuf_unittest::TestDiffMessage msg1;
+ msg1.add_rm()->set_c(1);
+ protobuf_unittest::TestDiffMessage msg2;
+ msg2.add_rm()->set_c(1);
+
+ ParentSavingFieldComparator field_comparator;
+ util::MessageDifferencer differencer;
+ differencer.set_field_comparator(&field_comparator);
+ differencer.Compare(msg1, msg2);
+
+ // We want only one parent with the name "rm"
+ ASSERT_EQ(1, field_comparator.parent_fields().size());
+ EXPECT_EQ("rm", field_comparator.parent_fields()[0].field->name());
+}
+
+
+class ComparisonTest : public testing::Test {
+ protected:
+ ComparisonTest() : use_equivalency_(false), repeated_field_as_set_(false) {
+ // Setup the test.
+ TestUtil::SetAllFields(&proto1_);
+ TestUtil::SetAllFields(&proto2_);
+
+ TestUtil::SetAllExtensions(&proto1ex_);
+ TestUtil::SetAllExtensions(&proto2ex_);
+
+ TestUtil::SetAllFieldsAndExtensions(&orderings_proto1_);
+ TestUtil::SetAllFieldsAndExtensions(&orderings_proto2_);
+
+ unknown1_ = empty1_.mutable_unknown_fields();
+ unknown2_ = empty2_.mutable_unknown_fields();
+ }
+
+ ~ComparisonTest() { }
+
+ void SetSpecialFieldOption(const Message& message,
+ util::MessageDifferencer* d) {
+ if (!ignored_field_.empty()) {
+ d->IgnoreField(GetFieldDescriptor(message, ignored_field_));
+ }
+
+ if (repeated_field_as_set_) {
+ d->set_repeated_field_comparison(util::MessageDifferencer::AS_SET);
+ }
+
+ if (!set_field_.empty()) {
+ d->TreatAsSet(GetFieldDescriptor(message, set_field_));
+ }
+
+ if (!map_field_.empty() && !map_key_.empty()) {
+ d->TreatAsMap(GetFieldDescriptor(message, map_field_),
+ GetFieldDescriptor(message, map_field_ + "." + map_key_));
+ }
+ }
+
+ string Run(const Message& msg1, const Message& msg2) {
+ string output;
+
+ // Setup the comparison.
+ util::MessageDifferencer differencer;
+ differencer.ReportDifferencesToString(&output);
+
+ if (use_equivalency_) {
+ differencer.set_message_field_comparison(
+ util::MessageDifferencer::EQUIVALENT);
+ }
+
+ SetSpecialFieldOption(msg1, &differencer);
+
+ // Conduct the comparison.
+ EXPECT_FALSE(differencer.Compare(msg1, msg2));
+
+ return output;
+ }
+
+ string Run() {
+ return Run(proto1_, proto2_);
+ }
+
+ string RunOrder() {
+ return Run(orderings_proto1_, orderings_proto2_);
+ }
+
+ string RunEx() {
+ return Run(proto1ex_, proto2ex_);
+ }
+
+ string RunDiff() {
+ return Run(proto1diff_, proto2diff_);
+ }
+
+ string RunUn() {
+ return Run(empty1_, empty2_);
+ }
+
+ void use_equivalency() {
+ use_equivalency_ = true;
+ }
+
+ void repeated_field_as_set() {
+ repeated_field_as_set_ = true;
+ }
+
+ void field_as_set(const string& field) {
+ set_field_ = field;
+ }
+
+ void field_as_map(const string& field, const string& key) {
+ map_field_ = field;
+ map_key_ = key;
+ }
+
+ void ignore_field(const string& field) {
+ ignored_field_ = field;
+ }
+
+ unittest::TestAllTypes proto1_;
+ unittest::TestAllTypes proto2_;
+
+ unittest::TestFieldOrderings orderings_proto1_;
+ unittest::TestFieldOrderings orderings_proto2_;
+
+ unittest::TestAllExtensions proto1ex_;
+ unittest::TestAllExtensions proto2ex_;
+
+ unittest::TestDiffMessage proto1diff_;
+ unittest::TestDiffMessage proto2diff_;
+
+ unittest::TestEmptyMessage empty1_;
+ unittest::TestEmptyMessage empty2_;
+
+ UnknownFieldSet* unknown1_;
+ UnknownFieldSet* unknown2_;
+
+ bool use_equivalency_;
+ bool repeated_field_as_set_;
+
+ string set_field_;
+ string map_field_;
+ string map_key_;
+ string ignored_field_;
+};
+
+// Basic tests.
+TEST_F(ComparisonTest, AdditionTest) {
+ proto1_.clear_optional_int32();
+
+ EXPECT_EQ("added: optional_int32: 101\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, Addition_OrderTest) {
+ orderings_proto1_.clear_my_int();
+
+ EXPECT_EQ("added: my_int: 1\n",
+ RunOrder());
+}
+
+TEST_F(ComparisonTest, DeletionTest) {
+ proto2_.clear_optional_int32();
+
+ EXPECT_EQ("deleted: optional_int32: 101\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, Deletion_OrderTest) {
+ orderings_proto2_.clear_my_string();
+
+ EXPECT_EQ("deleted: my_string: \"foo\"\n",
+ RunOrder());
+}
+
+TEST_F(ComparisonTest, RepeatedDeletionTest) {
+ proto2_.clear_repeated_int32();
+
+ EXPECT_EQ("deleted: repeated_int32[0]: 201\n"
+ "deleted: repeated_int32[1]: 301\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, ModificationTest) {
+ proto1_.set_optional_int32(-1);
+
+ EXPECT_EQ("modified: optional_int32: -1 -> 101\n",
+ Run());
+}
+
+// Basic equivalency tests.
+TEST_F(ComparisonTest, EquivalencyAdditionTest) {
+ use_equivalency();
+
+ proto1_.clear_optional_int32();
+
+ EXPECT_EQ("modified: optional_int32: 0 -> 101\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, EquivalencyDeletionTest) {
+ use_equivalency();
+
+ proto2_.clear_optional_int32();
+
+ EXPECT_EQ("modified: optional_int32: 101 -> 0\n",
+ Run());
+}
+
+// Group tests.
+TEST_F(ComparisonTest, GroupAdditionTest) {
+ proto1_.mutable_optionalgroup()->clear_a();
+
+ EXPECT_EQ("added: optionalgroup.a: 117\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, GroupDeletionTest) {
+ proto2_.mutable_optionalgroup()->clear_a();
+
+ EXPECT_EQ("deleted: optionalgroup.a: 117\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, GroupModificationTest) {
+ proto1_.mutable_optionalgroup()->set_a(2);
+
+ EXPECT_EQ("modified: optionalgroup.a: 2 -> 117\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, GroupFullAdditionTest) {
+ proto1_.clear_optionalgroup();
+
+ // Note the difference in the output between this and GroupAdditionTest.
+ EXPECT_EQ("added: optionalgroup: { a: 117 }\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, GroupFullDeletionTest) {
+ proto2_.clear_optionalgroup();
+
+ EXPECT_EQ("deleted: optionalgroup: { a: 117 }\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, RepeatedSetOptionTest) {
+ repeated_field_as_set();
+
+ proto2_.clear_repeatedgroup();
+ proto1_.clear_repeatedgroup();
+ proto1_.add_repeatedgroup()->set_a(317);
+ proto2_.add_repeatedgroup()->set_a(909);
+ proto2_.add_repeatedgroup()->set_a(907);
+ proto1_.add_repeatedgroup()->set_a(904);
+ proto1_.add_repeatedgroup()->set_a(907);
+ proto1_.add_repeatedgroup()->set_a(909);
+
+ EXPECT_EQ("moved: repeatedgroup[2] -> repeatedgroup[1] : { a: 907 }\n"
+ "moved: repeatedgroup[3] -> repeatedgroup[0] : { a: 909 }\n"
+ "deleted: repeatedgroup[0]: { a: 317 }\n"
+ "deleted: repeatedgroup[1]: { a: 904 }\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, RepeatedSetOptionTest_Ex) {
+ repeated_field_as_set();
+
+ proto1ex_.ClearExtension(protobuf_unittest::repeated_nested_message_extension);
+ proto2ex_.ClearExtension(protobuf_unittest::repeated_nested_message_extension);
+ proto2ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension)
+ ->set_bb(909);
+ proto2ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension)
+ ->set_bb(907);
+ proto1ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension)
+ ->set_bb(904);
+ proto1ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension)
+ ->set_bb(907);
+ proto1ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension)
+ ->set_bb(909);
+
+ EXPECT_EQ("moved: (protobuf_unittest.repeated_nested_message_extension)[2] ->"
+ " (protobuf_unittest.repeated_nested_message_extension)[0] :"
+ " { bb: 909 }\n"
+ "deleted: (protobuf_unittest.repeated_nested_message_extension)[0]:"
+ " { bb: 904 }\n",
+ RunEx());
+}
+
+TEST_F(ComparisonTest, RepeatedMapFieldTest_Group) {
+ field_as_map("repeatedgroup", "a");
+ proto1_.clear_repeatedgroup();
+ proto2_.clear_repeatedgroup();
+
+ proto1_.add_repeatedgroup()->set_a(317); // deleted
+ proto1_.add_repeatedgroup()->set_a(904); // deleted
+ proto1_.add_repeatedgroup()->set_a(907); // moved from
+ proto1_.add_repeatedgroup()->set_a(909); // moved from
+
+ proto2_.add_repeatedgroup()->set_a(909); // moved to
+ proto2_.add_repeatedgroup()->set_a(318); // added
+ proto2_.add_repeatedgroup()->set_a(907); // moved to
+
+ EXPECT_EQ("moved: repeatedgroup[3] -> repeatedgroup[0] : { a: 909 }\n"
+ "added: repeatedgroup[1]: { a: 318 }\n"
+ "deleted: repeatedgroup[0]: { a: 317 }\n"
+ "deleted: repeatedgroup[1]: { a: 904 }\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, RepeatedMapFieldTest_MessageKey) {
+ // Use m as key, but use b as value.
+ field_as_map("item", "m");
+
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+ protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+
+ // The following code creates one deletion, one addition and two moved fields
+ // on the messages.
+ item->mutable_m()->set_c(0);
+ item->set_b("first");
+ item = msg1.add_item();
+ item->mutable_m()->set_c(2);
+ item->set_b("second");
+ item = msg1.add_item(); item->set_b("null"); // empty key moved
+ item = msg1.add_item();
+ item->mutable_m()->set_c(3);
+ item->set_b("third"); // deletion
+ item = msg1.add_item();
+ item->mutable_m()->set_c(2);
+ item->set_b("second"); // duplicated key ( deletion )
+ item = msg2.add_item();
+ item->mutable_m()->set_c(2);
+ item->set_b("second"); // modification
+ item = msg2.add_item();
+ item->mutable_m()->set_c(4);
+ item->set_b("fourth"); // addition
+ item = msg2.add_item();
+ item->mutable_m()->set_c(0);
+ item->set_b("fist"); // move with change
+ item = msg2.add_item(); item->set_b("null");
+
+ EXPECT_EQ(
+ "modified: item[0].b -> item[2].b: \"first\" -> \"fist\"\n"
+ "moved: item[1] -> item[0] : { b: \"second\" m { c: 2 } }\n"
+ "moved: item[2] -> item[3] : { b: \"null\" }\n"
+ "added: item[1]: { b: \"fourth\" m { c: 4 } }\n"
+ "deleted: item[3]: { b: \"third\" m { c: 3 } }\n"
+ "deleted: item[4]: { b: \"second\" m { c: 2 } }\n",
+ Run(msg1, msg2));
+}
+
+TEST_F(ComparisonTest, RepeatedFieldSetTest_SetOfSet) {
+ repeated_field_as_set();
+ // Create the testing protos
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+
+ protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+ item->add_ra(1); item->add_ra(2); item->add_ra(3);
+ item = msg1.add_item();
+ item->add_ra(5); item->add_ra(6);
+ item = msg1.add_item();
+ item->add_ra(1); item->add_ra(3);
+ item = msg1.add_item();
+ item->add_ra(6); item->add_ra(7); item->add_ra(8);
+
+ item = msg2.add_item();
+ item->add_ra(6); item->add_ra(5);
+ item = msg2.add_item();
+ item->add_ra(6); item->add_ra(8);
+ item = msg2.add_item();
+ item->add_ra(1); item->add_ra(3);
+ item = msg2.add_item();
+ item->add_ra(3); item->add_ra(2); item->add_ra(1);
+
+ // Compare
+ EXPECT_EQ("moved: item[0].ra[0] -> item[3].ra[2] : 1\n"
+ "moved: item[0].ra[2] -> item[3].ra[0] : 3\n"
+ "moved: item[0] -> item[3] : { ra: 1 ra: 2 ra: 3 }\n"
+ "moved: item[1].ra[0] -> item[0].ra[1] : 5\n"
+ "moved: item[1].ra[1] -> item[0].ra[0] : 6\n"
+ "moved: item[1] -> item[0] : { ra: 5 ra: 6 }\n"
+ "added: item[1]: { ra: 6 ra: 8 }\n"
+ "deleted: item[3]: { ra: 6 ra: 7 ra: 8 }\n",
+ Run(msg1, msg2));
+}
+
+TEST_F(ComparisonTest, RepeatedMapFieldTest_RepeatedKey) {
+ // used rb as a key, but b is the value.
+ repeated_field_as_set();
+ field_as_map("item", "rb");
+
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+ protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+ item->add_rb("a");
+ item->add_rb("b");
+ item->set_b("first");
+
+ item = msg2.add_item();
+ item->add_rb("c");
+ item->set_b("second");
+
+ item = msg2.add_item();
+ item->add_rb("b");
+ item->add_rb("a");
+ item->set_b("fist");
+
+
+ EXPECT_EQ("modified: item[0].b -> item[1].b: \"first\" -> \"fist\"\n"
+ "moved: item[0].rb[0] -> item[1].rb[1] : \"a\"\n"
+ "moved: item[0].rb[1] -> item[1].rb[0] : \"b\"\n"
+ "added: item[0]: { b: \"second\" rb: \"c\" }\n",
+ Run(msg1, msg2));
+}
+
+TEST_F(ComparisonTest, RepeatedMapFieldTest_RepeatedMessageKey) {
+ field_as_map("item", "rm");
+
+ protobuf_unittest::TestDiffMessage msg1;
+ protobuf_unittest::TestDiffMessage msg2;
+ protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+ protobuf_unittest::TestField* key = item->add_rm();
+ key->set_c(2); key->add_rc(10); key->add_rc(10);
+ item = msg1.add_item(); key = item->add_rm();
+ key->set_c(0); key->add_rc(1); key->add_rc(2);
+ key = item->add_rm();
+ key->set_c(0);
+ item->add_rb("first");
+
+ item = msg2.add_item();
+ item->CopyFrom(msg1.item(1));
+ item->add_rb("second");
+
+ EXPECT_EQ("added: item[0].rb[1]: \"second\"\n"
+ "deleted: item[0]: { rm { c: 2 rc: 10 rc: 10 } }\n",
+ Run(msg1, msg2));
+}
+
+TEST_F(ComparisonTest, RepeatedSetOptionTest_Unknown) {
+ // Currently, as_set option doens't have affects on unknown field.
+ // If needed, this feature will be added by request.
+ repeated_field_as_set();
+ unknown1_->AddGroup(245)->AddFixed32(248, 1);
+ unknown2_->AddGroup(245)->AddFixed32(248, 3);
+ unknown2_->AddGroup(245)->AddFixed32(248, 1);
+
+ // We expect it behaves the same as normal comparison.
+ EXPECT_EQ("modified: 245[0].248[0]: 0x00000001 -> 0x00000003\n"
+ "added: 245[1]: { ... }\n",
+ RunUn());
+}
+
+TEST_F(ComparisonTest, Matching_Unknown) {
+ unknown1_->AddGroup(245)->AddFixed32(248, 1);
+ unknown2_->AddGroup(245)->AddFixed32(248, 1);
+ unknown1_->AddGroup(245)->AddFixed32(248, 3);
+ unknown2_->AddGroup(245)->AddFixed32(248, 3);
+ unknown2_->AddLengthDelimited(242, "cat");
+ unknown2_->AddGroup(246)->AddFixed32(248, 4);
+
+ // report_match is false so only added/modified fields are expected.
+ EXPECT_EQ("added: 242[0]: \"cat\"\n"
+ "added: 246[0]: { ... }\n",
+ RunUn());
+}
+
+TEST_F(ComparisonTest, RepeatedSetFieldTest) {
+ field_as_set("repeatedgroup");
+
+ proto1_.clear_repeatedgroup();
+ proto2_.clear_repeatedgroup();
+ proto2_.add_repeatedgroup()->set_a(909);
+ proto2_.add_repeatedgroup()->set_a(907);
+ proto1_.add_repeatedgroup()->set_a(317);
+ proto1_.add_repeatedgroup()->set_a(904);
+ proto1_.add_repeatedgroup()->set_a(907);
+ proto1_.add_repeatedgroup()->set_a(909);
+
+ EXPECT_EQ("moved: repeatedgroup[2] -> repeatedgroup[1] : { a: 907 }\n"
+ "moved: repeatedgroup[3] -> repeatedgroup[0] : { a: 909 }\n"
+ "deleted: repeatedgroup[0]: { a: 317 }\n"
+ "deleted: repeatedgroup[1]: { a: 904 }\n",
+ Run());
+}
+
+// Embedded message tests.
+TEST_F(ComparisonTest, EmbeddedAdditionTest) {
+ proto1_.mutable_optional_nested_message()->clear_bb();
+
+ EXPECT_EQ("added: optional_nested_message.bb: 118\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, EmbeddedDeletionTest) {
+ proto2_.mutable_optional_nested_message()->clear_bb();
+
+ EXPECT_EQ("deleted: optional_nested_message.bb: 118\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, EmbeddedModificationTest) {
+ proto1_.mutable_optional_nested_message()->set_bb(2);
+
+ EXPECT_EQ("modified: optional_nested_message.bb: 2 -> 118\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, EmbeddedFullAdditionTest) {
+ proto1_.clear_optional_nested_message();
+
+ EXPECT_EQ("added: optional_nested_message: { bb: 118 }\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, EmbeddedPartialAdditionTest) {
+ proto1_.clear_optional_nested_message();
+ proto2_.mutable_optional_nested_message()->clear_bb();
+
+ EXPECT_EQ("added: optional_nested_message: { }\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, EmbeddedFullDeletionTest) {
+ proto2_.clear_optional_nested_message();
+
+ EXPECT_EQ("deleted: optional_nested_message: { bb: 118 }\n",
+ Run());
+}
+
+// Repeated element tests.
+TEST_F(ComparisonTest, BasicRepeatedTest) {
+ proto1_.clear_repeated_int32();
+ proto2_.clear_repeated_int32();
+
+ proto1_.add_repeated_int32(500);
+ proto1_.add_repeated_int32(501);
+ proto1_.add_repeated_int32(502);
+ proto1_.add_repeated_int32(503);
+ proto1_.add_repeated_int32(500);
+
+ proto2_.add_repeated_int32(500);
+ proto2_.add_repeated_int32(509);
+ proto2_.add_repeated_int32(502);
+ proto2_.add_repeated_int32(504);
+
+ EXPECT_EQ("modified: repeated_int32[1]: 501 -> 509\n"
+ "modified: repeated_int32[3]: 503 -> 504\n"
+ "deleted: repeated_int32[4]: 500\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, BasicRepeatedTest_SetOption) {
+ repeated_field_as_set();
+ proto1_.clear_repeated_int32();
+ proto2_.clear_repeated_int32();
+
+ proto1_.add_repeated_int32(501);
+ proto1_.add_repeated_int32(502);
+ proto1_.add_repeated_int32(503);
+ proto1_.add_repeated_int32(500);
+ proto1_.add_repeated_int32(500);
+
+ proto2_.add_repeated_int32(500);
+ proto2_.add_repeated_int32(509);
+ proto2_.add_repeated_int32(503);
+ proto2_.add_repeated_int32(502);
+ proto2_.add_repeated_int32(504);
+
+ EXPECT_EQ("moved: repeated_int32[1] -> repeated_int32[3] : 502\n"
+ "moved: repeated_int32[3] -> repeated_int32[0] : 500\n"
+ "added: repeated_int32[1]: 509\n"
+ "added: repeated_int32[4]: 504\n"
+ "deleted: repeated_int32[0]: 501\n"
+ "deleted: repeated_int32[4]: 500\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, BasicRepeatedTest_SetField) {
+ field_as_set("repeated_int32");
+ proto1_.clear_repeated_int32();
+ proto2_.clear_repeated_int32();
+
+ proto1_.add_repeated_int32(501);
+ proto1_.add_repeated_int32(502);
+ proto1_.add_repeated_int32(503);
+ proto1_.add_repeated_int32(500);
+ proto1_.add_repeated_int32(500);
+
+ proto2_.add_repeated_int32(500);
+ proto2_.add_repeated_int32(509);
+ proto2_.add_repeated_int32(503);
+ proto2_.add_repeated_int32(502);
+ proto2_.add_repeated_int32(504);
+
+ EXPECT_EQ("moved: repeated_int32[1] -> repeated_int32[3] : 502\n"
+ "moved: repeated_int32[3] -> repeated_int32[0] : 500\n"
+ "added: repeated_int32[1]: 509\n"
+ "added: repeated_int32[4]: 504\n"
+ "deleted: repeated_int32[0]: 501\n"
+ "deleted: repeated_int32[4]: 500\n",
+ Run());
+}
+
+// Multiple action tests.
+TEST_F(ComparisonTest, AddDeleteTest) {
+ proto1_.clear_optional_int32();
+ proto2_.clear_optional_int64();
+
+ EXPECT_EQ("added: optional_int32: 101\n"
+ "deleted: optional_int64: 102\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, AddDelete_FieldOrderingTest) {
+ orderings_proto1_.ClearExtension(unittest::my_extension_string);
+ orderings_proto2_.clear_my_int();
+
+ EXPECT_EQ("deleted: my_int: 1\n"
+ "added: (protobuf_unittest.my_extension_string): \"bar\"\n",
+ RunOrder());
+}
+
+TEST_F(ComparisonTest, AllThreeTest) {
+ proto1_.clear_optional_int32();
+ proto2_.clear_optional_float();
+ proto2_.set_optional_string("hello world!");
+
+ EXPECT_EQ("added: optional_int32: 101\n"
+ "deleted: optional_float: 111\n"
+ "modified: optional_string: \"115\" -> \"hello world!\"\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, SandwhichTest) {
+ proto1_.clear_optional_int64();
+ proto1_.clear_optional_uint32();
+
+ proto2_.clear_optional_uint64();
+
+ EXPECT_EQ("added: optional_int64: 102\n"
+ "added: optional_uint32: 103\n"
+ "deleted: optional_uint64: 104\n",
+ Run());
+}
+
+TEST_F(ComparisonTest, IgnoredNoChangeTest) {
+ proto1diff_.set_v(3);
+ proto2diff_.set_v(3);
+ proto2diff_.set_w("foo");
+
+ ignore_field("v");
+
+ EXPECT_EQ("ignored: v\n"
+ "added: w: \"foo\"\n",
+ RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredAddTest) {
+ proto2diff_.set_v(3);
+ proto2diff_.set_w("foo");
+
+ ignore_field("v");
+
+ EXPECT_EQ("ignored: v\n"
+ "added: w: \"foo\"\n",
+ RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredDeleteTest) {
+ proto1diff_.set_v(3);
+ proto2diff_.set_w("foo");
+
+ ignore_field("v");
+
+ EXPECT_EQ("ignored: v\n"
+ "added: w: \"foo\"\n",
+ RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredModifyTest) {
+ proto1diff_.set_v(3);
+ proto2diff_.set_v(4);
+ proto2diff_.set_w("foo");
+
+ ignore_field("v");
+
+ EXPECT_EQ("ignored: v\n"
+ "added: w: \"foo\"\n",
+ RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredRepeatedAddTest) {
+ proto1diff_.add_rv(3);
+ proto1diff_.add_rv(4);
+
+ proto2diff_.add_rv(3);
+ proto2diff_.add_rv(4);
+ proto2diff_.add_rv(5);
+
+ proto2diff_.set_w("foo");
+
+ ignore_field("rv");
+
+ EXPECT_EQ("ignored: rv\n"
+ "added: w: \"foo\"\n",
+ RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredRepeatedDeleteTest) {
+ proto1diff_.add_rv(3);
+ proto1diff_.add_rv(4);
+ proto1diff_.add_rv(5);
+
+ proto2diff_.add_rv(3);
+ proto2diff_.add_rv(4);
+
+ proto2diff_.set_w("foo");
+
+ ignore_field("rv");
+
+ EXPECT_EQ("ignored: rv\n"
+ "added: w: \"foo\"\n",
+ RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredRepeatedModifyTest) {
+ proto1diff_.add_rv(3);
+ proto1diff_.add_rv(4);
+
+ proto2diff_.add_rv(3);
+ proto2diff_.add_rv(5);
+
+ proto2diff_.set_w("foo");
+
+ ignore_field("rv");
+
+ EXPECT_EQ("ignored: rv\n"
+ "added: w: \"foo\"\n",
+ RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredWholeNestedMessage) {
+ proto1diff_.mutable_m()->set_c(3);
+ proto2diff_.mutable_m()->set_c(4);
+
+ proto2diff_.set_w("foo");
+
+ ignore_field("m");
+
+ EXPECT_EQ("added: w: \"foo\"\n"
+ "ignored: m\n",
+ RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredNestedField) {
+ proto1diff_.mutable_m()->set_c(3);
+ proto2diff_.mutable_m()->set_c(4);
+
+ proto2diff_.set_w("foo");
+
+ ignore_field("m.c");
+
+ EXPECT_EQ("added: w: \"foo\"\n"
+ "ignored: m.c\n",
+ RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredRepeatedNested) {
+ proto1diff_.add_rm()->set_c(0);
+ proto1diff_.add_rm()->set_c(1);
+ proto2diff_.add_rm()->set_c(2);
+ proto2diff_.add_rm()->set_c(3);
+
+ proto2diff_.set_w("foo");
+
+ ignore_field("rm.c");
+
+ EXPECT_EQ("ignored: rm[0].c\n"
+ "ignored: rm[1].c\n"
+ "added: w: \"foo\"\n",
+ RunDiff());
+}
+
+TEST_F(ComparisonTest, IgnoredNestedRepeated) {
+ proto1diff_.mutable_m()->add_rc(23);
+ proto1diff_.mutable_m()->add_rc(24);
+ proto2diff_.mutable_m()->add_rc(25);
+
+ proto2diff_.set_w("foo");
+
+ ignore_field("m.rc");
+
+ EXPECT_EQ("added: w: \"foo\"\n"
+ "ignored: m.rc\n",
+ RunDiff());
+}
+
+TEST_F(ComparisonTest, ExtensionTest) {
+ proto1ex_.SetExtension(unittest::optional_int32_extension, 401);
+ proto2ex_.SetExtension(unittest::optional_int32_extension, 402);
+
+ proto1ex_.ClearExtension(unittest::optional_int64_extension);
+ proto2ex_.SetExtension(unittest::optional_int64_extension, 403);
+
+ EXPECT_EQ(
+ "modified: (protobuf_unittest.optional_int32_extension): 401 -> 402\n"
+ "added: (protobuf_unittest.optional_int64_extension): 403\n",
+ RunEx());
+}
+
+TEST_F(ComparisonTest, MatchedUnknownFieldTagTest) {
+ unknown1_->AddVarint(240, 122);
+ unknown2_->AddVarint(240, 121);
+ unknown1_->AddFixed32(241, 1);
+ unknown2_->AddFixed64(241, 2);
+ unknown1_->AddLengthDelimited(242, "cat");
+ unknown2_->AddLengthDelimited(242, "dog");
+
+ EXPECT_EQ(
+ "modified: 240[0]: 122 -> 121\n"
+ "deleted: 241[0]: 0x00000001\n"
+ "added: 241[0]: 0x0000000000000002\n"
+ "modified: 242[0]: \"cat\" -> \"dog\"\n",
+ RunUn());
+}
+
+TEST_F(ComparisonTest, UnmatchedUnknownFieldTagTest) {
+ unknown1_->AddFixed32(243, 1);
+ unknown2_->AddVarint(244, 2);
+ unknown2_->AddVarint(244, 4);
+
+ EXPECT_EQ(
+ "deleted: 243[0]: 0x00000001\n"
+ "added: 244[0]: 2\n"
+ "added: 244[1]: 4\n",
+ RunUn());
+}
+
+TEST_F(ComparisonTest, DifferentSizedUnknownFieldTest) {
+ unknown1_->AddVarint(240, 1);
+ unknown1_->AddVarint(240, 3);
+ unknown1_->AddVarint(240, 4);
+ unknown2_->AddVarint(240, 2);
+ unknown2_->AddVarint(240, 3);
+ unknown2_->AddVarint(240, 2);
+ unknown2_->AddVarint(240, 5);
+
+ EXPECT_EQ(
+ "modified: 240[0]: 1 -> 2\n"
+ "modified: 240[2]: 4 -> 2\n"
+ "added: 240[3]: 5\n",
+ RunUn());
+}
+
+TEST_F(ComparisonTest, UnknownFieldsAll) {
+ unknown1_->AddVarint(243, 122);
+ unknown1_->AddFixed64(244, 0x0172356);
+ unknown1_->AddFixed64(244, 0x098);
+ unknown1_->AddGroup(245)->AddFixed32(248, 1);
+ unknown1_->mutable_field(3)->mutable_group()->AddFixed32(248, 2);
+ unknown1_->AddGroup(249)->AddFixed64(250, 1);
+
+ unknown2_->AddVarint(243, 121);
+ unknown2_->AddLengthDelimited(73882, "test 123");
+ unknown2_->AddGroup(245)->AddFixed32(248, 3);
+ unknown2_->AddGroup(247);
+
+ EXPECT_EQ(
+ "modified: 243[0]: 122 -> 121\n"
+ "deleted: 244[0]: 0x0000000000172356\n"
+ "deleted: 244[1]: 0x0000000000000098\n"
+ "modified: 245[0].248[0]: 0x00000001 -> 0x00000003\n"
+ "deleted: 245[0].248[1]: 0x00000002\n"
+ "added: 247[0]: { ... }\n"
+ "deleted: 249[0]: { ... }\n"
+ "added: 73882[0]: \"test 123\"\n",
+ RunUn());
+}
+
+TEST_F(ComparisonTest, EquivalentIgnoresUnknown) {
+ unittest::ForeignMessage message1, message2;
+
+ message1.set_c(5);
+ message1.mutable_unknown_fields()->AddVarint(123, 456);
+ message2.set_c(5);
+ message2.mutable_unknown_fields()->AddVarint(321, 654);
+
+ EXPECT_FALSE(util::MessageDifferencer::Equals(message1, message2));
+ EXPECT_TRUE(util::MessageDifferencer::Equivalent(message1, message2));
+}
+
+class MatchingTest : public testing::Test {
+ public:
+ typedef util::MessageDifferencer MessageDifferencer;
+
+ protected:
+ MatchingTest() {
+ }
+
+ ~MatchingTest() {
+ }
+
+ string RunWithResult(MessageDifferencer* differencer,
+ const Message& msg1, const Message& msg2,
+ bool result) {
+ string output;
+ io::StringOutputStream output_stream(&output);
+ MessageDifferencer::StreamReporter reporter(&output_stream);
+ reporter.set_report_modified_aggregates(true);
+ differencer->set_report_matches(true);
+ differencer->ReportDifferencesTo(&reporter);
+ if (result) {
+ EXPECT_TRUE(differencer->Compare(msg1, msg2));
+ } else {
+ EXPECT_FALSE(differencer->Compare(msg1, msg2));
+ }
+ return output;
+ }
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MatchingTest);
+};
+
+TEST_F(MatchingTest, StreamReporterMatching) {
+ protobuf_unittest::TestField msg1, msg2;
+ msg1.set_c(72);
+ msg2.set_c(72);
+ msg1.add_rc(13);
+ msg2.add_rc(13);
+ msg1.add_rc(17);
+ msg2.add_rc(17);
+ string output;
+ MessageDifferencer differencer;
+ differencer.set_report_matches(true);
+ differencer.ReportDifferencesToString(&output);
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+ EXPECT_EQ(
+ "matched: c : 72\n"
+ "matched: rc[0] : 13\n"
+ "matched: rc[1] : 17\n",
+ output);
+}
+
+TEST_F(MatchingTest, DontReportMatchedWhenIgnoring) {
+ protobuf_unittest::TestField msg1, msg2;
+ msg1.set_c(72);
+ msg2.set_c(72);
+ msg1.add_rc(13);
+ msg2.add_rc(13);
+ msg1.add_rc(17);
+ msg2.add_rc(17);
+ string output;
+ MessageDifferencer differencer;
+ differencer.set_report_matches(true);
+ differencer.ReportDifferencesToString(&output);
+
+ differencer.IgnoreField(msg1.GetDescriptor()->FindFieldByName("c"));
+
+ EXPECT_TRUE(differencer.Compare(msg1, msg2));
+ EXPECT_EQ(
+ "ignored: c\n"
+ "matched: rc[0] : 13\n"
+ "matched: rc[1] : 17\n",
+ output);
+}
+
+TEST_F(MatchingTest, ReportMatchedForMovedFields) {
+ protobuf_unittest::TestDiffMessage msg1, msg2;
+ protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+ item->set_a(53);
+ item->set_b("hello");
+ item = msg2.add_item();
+ item->set_a(27);
+ item = msg2.add_item();
+ item->set_a(53);
+ item->set_b("hello");
+ item = msg1.add_item();
+ item->set_a(27);
+ MessageDifferencer differencer;
+ const FieldDescriptor* desc;
+ desc = msg1.GetDescriptor()->FindFieldByName("item");
+ differencer.TreatAsSet(desc);
+
+ EXPECT_EQ(
+ "matched: item[0].a -> item[1].a : 53\n"
+ "matched: item[0].b -> item[1].b : \"hello\"\n"
+ "moved: item[0] -> item[1] : { a: 53 b: \"hello\" }\n"
+ "matched: item[1].a -> item[0].a : 27\n"
+ "moved: item[1] -> item[0] : { a: 27 }\n",
+ RunWithResult(&differencer, msg1, msg2, true));
+}
+
+TEST_F(MatchingTest, MatchesAppearInPostTraversalOrderForMovedFields) {
+ protobuf_unittest::TestDiffMessage msg1, msg2;
+ protobuf_unittest::TestDiffMessage::Item* item;
+ protobuf_unittest::TestField* field;
+
+ const FieldDescriptor* desc;
+ const FieldDescriptor* nested_desc;
+ const FieldDescriptor* double_nested_desc;
+ desc = msg1.GetDescriptor()->FindFieldByName("item");
+ nested_desc = desc->message_type()->FindFieldByName("rm");
+ double_nested_desc = nested_desc->message_type()->FindFieldByName("rc");
+ MessageDifferencer differencer;
+ differencer.TreatAsSet(desc);
+ differencer.TreatAsSet(nested_desc);
+ differencer.TreatAsSet(double_nested_desc);
+
+ item = msg1.add_item();
+ field = item->add_rm();
+ field->set_c(1);
+ field->add_rc(2);
+ field->add_rc(3);
+ field = item->add_rm();
+ field->set_c(4);
+ field->add_rc(5);
+ field->add_rc(6);
+ field->add_rc(7);
+ item = msg2.add_item();
+ field = item->add_rm();
+ field->set_c(4);
+ field->add_rc(7);
+ field->add_rc(6);
+ field->add_rc(5);
+ field = item->add_rm();
+ field->set_c(1);
+ field->add_rc(3);
+ field->add_rc(2);
+ item = msg1.add_item();
+ field = item->add_rm();
+ field->set_c(8);
+ field->add_rc(10);
+ field->add_rc(11);
+ field->add_rc(9);
+ item = msg2.add_item();
+ field = item->add_rm();
+ field->set_c(8);
+ field->add_rc(9);
+ field->add_rc(10);
+ field->add_rc(11);
+
+ EXPECT_EQ(
+ "matched: item[0].rm[0].c -> item[0].rm[1].c : 1\n"
+ "moved: item[0].rm[0].rc[0] -> item[0].rm[1].rc[1] : 2\n"
+ "moved: item[0].rm[0].rc[1] -> item[0].rm[1].rc[0] : 3\n"
+ "moved: item[0].rm[0] -> item[0].rm[1] : { c: 1 rc: 2 rc: 3 }\n"
+ "matched: item[0].rm[1].c -> item[0].rm[0].c : 4\n"
+ "moved: item[0].rm[1].rc[0] -> item[0].rm[0].rc[2] : 5\n"
+ "matched: item[0].rm[1].rc[1] -> item[0].rm[0].rc[1] : 6\n"
+ "moved: item[0].rm[1].rc[2] -> item[0].rm[0].rc[0] : 7\n"
+ "moved: item[0].rm[1] -> item[0].rm[0] : { c: 4 rc: 5 rc: 6 rc: 7 }\n"
+ "matched: item[0] : { rm { c: 1 rc: 2 rc: 3 }"
+ " rm { c: 4 rc: 5 rc: 6 rc: 7 } }\n"
+ "matched: item[1].rm[0].c : 8\n"
+ "moved: item[1].rm[0].rc[0] -> item[1].rm[0].rc[1] : 10\n"
+ "moved: item[1].rm[0].rc[1] -> item[1].rm[0].rc[2] : 11\n"
+ "moved: item[1].rm[0].rc[2] -> item[1].rm[0].rc[0] : 9\n"
+ "matched: item[1].rm[0] : { c: 8 rc: 10 rc: 11 rc: 9 }\n"
+ "matched: item[1] : { rm { c: 8 rc: 10 rc: 11 rc: 9 } }\n",
+ RunWithResult(&differencer, msg1, msg2, true));
+}
+
+TEST_F(MatchingTest, MatchAndModifiedInterleaveProperly) {
+ protobuf_unittest::TestDiffMessage msg1, msg2;
+ protobuf_unittest::TestDiffMessage::Item* item;
+ protobuf_unittest::TestField* field;
+
+ const FieldDescriptor* desc;
+ const FieldDescriptor* nested_key;
+ const FieldDescriptor* nested_desc;
+ const FieldDescriptor* double_nested_key;
+ const FieldDescriptor* double_nested_desc;
+ desc = msg1.GetDescriptor()->FindFieldByName("item");
+ nested_key = desc->message_type()->FindFieldByName("a");
+ nested_desc = desc->message_type()->FindFieldByName("rm");
+ double_nested_key = nested_desc->message_type()->FindFieldByName("c");
+ double_nested_desc = nested_desc->message_type()->FindFieldByName("rc");
+
+ MessageDifferencer differencer;
+ differencer.TreatAsMap(desc, nested_key);
+ differencer.TreatAsMap(nested_desc, double_nested_key);
+ differencer.TreatAsSet(double_nested_desc);
+
+ item = msg1.add_item();
+ item->set_a(1);
+ field = item->add_rm();
+ field->set_c(2);
+ field->add_rc(3);
+ field->add_rc(4);
+ field = item->add_rm();
+ field->set_c(5);
+ field->add_rc(6);
+ field->add_rc(7);
+ field->add_rc(8);
+ item = msg1.add_item();
+ item->set_a(9);
+ field = item->add_rm();
+ field->set_c(10);
+ field->add_rc(11);
+ field->add_rc(12);
+ field = item->add_rm();
+ field->set_c(13);
+
+ item = msg2.add_item();
+ item->set_a(1);
+ field = item->add_rm();
+ field->set_c(5);
+ field->add_rc(8);
+ field->add_rc(8);
+ field->add_rc(6);
+ field = item->add_rm();
+ field->set_c(3);
+ field->add_rc(2);
+ field->add_rc(4);
+ item = msg2.add_item();
+ item->set_a(9);
+ field = item->add_rm();
+ field->set_c(10);
+ field->add_rc(12);
+ field->add_rc(11);
+ field = item->add_rm();
+ field->set_c(13);
+
+ EXPECT_EQ(
+ "matched: item[0].a : 1\n"
+ "matched: item[0].rm[1].c -> item[0].rm[0].c : 5\n"
+ "moved: item[0].rm[1].rc[0] -> item[0].rm[0].rc[2] : 6\n"
+ "moved: item[0].rm[1].rc[2] -> item[0].rm[0].rc[0] : 8\n"
+ "added: item[0].rm[0].rc[1]: 8\n"
+ "deleted: item[0].rm[1].rc[1]: 7\n"
+ "modified: item[0].rm[1] -> item[0].rm[0]: { c: 5 rc: 6 rc: 7 rc: 8 } ->"
+ " { c: 5 rc: 8 rc: 8 rc: 6 }\n"
+ "added: item[0].rm[1]: { c: 3 rc: 2 rc: 4 }\n"
+ "deleted: item[0].rm[0]: { c: 2 rc: 3 rc: 4 }\n"
+ "modified: item[0]: { a: 1 rm { c: 2 rc: 3 rc: 4 }"
+ " rm { c: 5 rc: 6 rc: 7 rc: 8 } } ->"
+ " { a: 1 rm { c: 5 rc: 8 rc: 8 rc: 6 }"
+ " rm { c: 3 rc: 2 rc: 4 } }\n"
+ "matched: item[1].a : 9\n"
+ "matched: item[1].rm[0].c : 10\n"
+ "moved: item[1].rm[0].rc[0] -> item[1].rm[0].rc[1] : 11\n"
+ "moved: item[1].rm[0].rc[1] -> item[1].rm[0].rc[0] : 12\n"
+ "matched: item[1].rm[0] : { c: 10 rc: 11 rc: 12 }\n"
+ "matched: item[1].rm[1].c : 13\n"
+ "matched: item[1].rm[1] : { c: 13 }\n"
+ "matched: item[1] : { a: 9 rm { c: 10 rc: 11 rc: 12 } rm { c: 13 } }\n",
+ RunWithResult(&differencer, msg1, msg2, false));
+}
+
+TEST_F(MatchingTest, MatchingWorksWithExtensions) {
+ protobuf_unittest::TestAllExtensions msg1, msg2;
+ protobuf_unittest::TestAllTypes::NestedMessage* nested;
+ using protobuf_unittest::repeated_nested_message_extension;
+
+ const FileDescriptor* descriptor;
+ const FieldDescriptor* desc;
+ const FieldDescriptor* nested_key;
+ descriptor = msg1.GetDescriptor()->file();
+ desc = descriptor->FindExtensionByName("repeated_nested_message_extension");
+ ASSERT_FALSE(desc == NULL);
+ nested_key = desc->message_type()->FindFieldByName("bb");
+
+ MessageDifferencer differencer;
+ differencer.TreatAsMap(desc, nested_key);
+
+ nested = msg1.AddExtension(repeated_nested_message_extension);
+ nested->set_bb(7);
+ nested = msg1.AddExtension(repeated_nested_message_extension);
+ nested->set_bb(13);
+ nested = msg1.AddExtension(repeated_nested_message_extension);
+ nested->set_bb(11);
+ nested = msg2.AddExtension(repeated_nested_message_extension);
+ nested->set_bb(11);
+ nested = msg2.AddExtension(repeated_nested_message_extension);
+ nested->set_bb(13);
+ nested = msg2.AddExtension(repeated_nested_message_extension);
+ nested->set_bb(7);
+
+ EXPECT_EQ(
+ "matched: (protobuf_unittest.repeated_nested_message_extension)[0].bb ->"
+ " (protobuf_unittest.repeated_nested_message_extension)[2].bb : 7\n"
+ "moved: (protobuf_unittest.repeated_nested_message_extension)[0] ->"
+ " (protobuf_unittest.repeated_nested_message_extension)[2] :"
+ " { bb: 7 }\n"
+ "matched: (protobuf_unittest.repeated_nested_message_extension)[1].bb :"
+ " 13\n"
+ "matched: (protobuf_unittest.repeated_nested_message_extension)[1] :"
+ " { bb: 13 }\n"
+ "matched: (protobuf_unittest.repeated_nested_message_extension)[2].bb ->"
+ " (protobuf_unittest.repeated_nested_message_extension)[0].bb :"
+ " 11\n"
+ "moved: (protobuf_unittest.repeated_nested_message_extension)[2] ->"
+ " (protobuf_unittest.repeated_nested_message_extension)[0] :"
+ " { bb: 11 }\n",
+ RunWithResult(&differencer, msg1, msg2, true));
+}
+
+TEST(AnyTest, Simple) {
+ protobuf_unittest::TestField value1, value2;
+ value1.set_a(20);
+ value2.set_a(21);
+
+ protobuf_unittest::TestAny m1, m2;
+ m1.mutable_any_value()->PackFrom(value1);
+ m2.mutable_any_value()->PackFrom(value2);
+ util::MessageDifferencer message_differencer;
+ string difference_string;
+ message_differencer.ReportDifferencesToString(&difference_string);
+ EXPECT_FALSE(message_differencer.Compare(m1, m2));
+ EXPECT_EQ("modified: any_value.a: 20 -> 21\n", difference_string);
+}
+
+TEST(Anytest, TreatAsSet) {
+ protobuf_unittest::TestField value1, value2;
+ value1.set_a(20);
+ value1.set_b(30);
+ value2.set_a(20);
+ value2.set_b(31);
+
+ protobuf_unittest::TestAny m1, m2;
+ m1.add_repeated_any_value()->PackFrom(value1);
+ m1.add_repeated_any_value()->PackFrom(value2);
+ m2.add_repeated_any_value()->PackFrom(value2);
+ m2.add_repeated_any_value()->PackFrom(value1);
+
+ util::MessageDifferencer message_differencer;
+ message_differencer.TreatAsSet(GetFieldDescriptor(m1, "repeated_any_value"));
+ EXPECT_TRUE(message_differencer.Compare(m1, m2));
+}
+
+
+} // namespace
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/message_differencer_unittest.proto b/src/google/protobuf/util/message_differencer_unittest.proto
new file mode 100644
index 00000000..698775f1
--- /dev/null
+++ b/src/google/protobuf/util/message_differencer_unittest.proto
@@ -0,0 +1,74 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file contains messages for testing repeated field comparison
+
+syntax = "proto2";
+package protobuf_unittest;
+
+option optimize_for = SPEED;
+
+message TestField {
+ optional int32 a = 3;
+ optional int32 b = 4;
+ optional int32 c = 1;
+ repeated int32 rc = 2;
+ optional TestField m = 5;
+
+ extend TestDiffMessage {
+ optional TestField tf = 100;
+ }
+}
+
+message TestDiffMessage {
+ repeated group Item = 1 {
+ optional int32 a = 2; // Test basic repeated field comparison.
+ optional string b = 4; // Test basic repeated field comparison.
+ repeated int32 ra = 3; // Test SetOfSet Comparison.
+ repeated string rb = 5; // Test TreatAsMap when key is repeated
+ optional TestField m = 6; // Test TreatAsMap when key is a message
+ repeated TestField rm = 7; // Test TreatAsMap when key is a repeated
+ // message
+ }
+
+ optional int32 v = 13 [deprecated = true];
+ optional string w = 14;
+ optional TestField m = 15;
+ repeated int32 rv = 11; // Test for combinations
+ repeated string rw = 10; // Test for combinations
+ repeated TestField rm = 12 [deprecated = true]; // Test for combinations
+
+ extensions 100 to 199;
+}
+
diff --git a/src/google/protobuf/util/type_resolver.h b/src/google/protobuf/util/type_resolver.h
new file mode 100644
index 00000000..77d4416a
--- /dev/null
+++ b/src/google/protobuf/util/type_resolver.h
@@ -0,0 +1,75 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__
+#define GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/status.h>
+
+
+namespace google {
+namespace protobuf {
+class Type;
+class Enum;
+} // namespace protobuf
+
+
+namespace protobuf {
+class DescriptorPool;
+namespace util {
+
+// Abstract interface for a type resovler.
+//
+// Implementations of this interface must be thread-safe.
+class LIBPROTOBUF_EXPORT TypeResolver {
+ public:
+ TypeResolver() {}
+ virtual ~TypeResolver() {}
+
+ // Resolves a type url for a message type.
+ virtual util::Status ResolveMessageType(
+ const string& type_url, google::protobuf::Type* message_type) = 0;
+
+ // Resolves a type url for an enum type.
+ virtual util::Status ResolveEnumType(const string& type_url,
+ google::protobuf::Enum* enum_type) = 0;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeResolver);
+};
+
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__
diff --git a/src/google/protobuf/util/type_resolver_util.cc b/src/google/protobuf/util/type_resolver_util.cc
new file mode 100644
index 00000000..053a4ed7
--- /dev/null
+++ b/src/google/protobuf/util/type_resolver_util.cc
@@ -0,0 +1,212 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/type_resolver_util.h>
+
+#include <google/protobuf/type.pb.h>
+#include <google/protobuf/wrappers.pb.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/status.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace {
+using google::protobuf::BoolValue;
+using google::protobuf::Enum;
+using google::protobuf::EnumValue;
+using google::protobuf::Field;
+using google::protobuf::Option;
+using google::protobuf::Type;
+
+using util::Status;
+using util::error::INVALID_ARGUMENT;
+using util::error::NOT_FOUND;
+
+bool SplitTypeUrl(const string& type_url,
+ string* url_prefix,
+ string* message_name) {
+ size_t pos = type_url.find_last_of("/");
+ if (pos == string::npos) {
+ return false;
+ }
+ *url_prefix = type_url.substr(0, pos);
+ *message_name = type_url.substr(pos + 1);
+ return true;
+}
+
+
+class DescriptorPoolTypeResolver : public TypeResolver {
+ public:
+ DescriptorPoolTypeResolver(const string& url_prefix,
+ const DescriptorPool* pool)
+ : url_prefix_(url_prefix), pool_(pool) {
+ }
+
+ Status ResolveMessageType(const string& type_url, Type* type) {
+ string url_prefix, message_name;
+ if (!SplitTypeUrl(type_url, &url_prefix, &message_name) ||
+ url_prefix != url_prefix_) {
+ return Status(INVALID_ARGUMENT, "Failed to parse type url: " + type_url);
+ }
+ if (url_prefix != url_prefix_) {
+ return Status(INVALID_ARGUMENT,
+ "Cannot resolve types from URL: " + url_prefix);
+ }
+ const Descriptor* descriptor = pool_->FindMessageTypeByName(message_name);
+ if (descriptor == NULL) {
+ return Status(NOT_FOUND, "Cannot found the type: " + message_name);
+ }
+ ConvertDescriptor(descriptor, type);
+ return Status();
+ }
+
+ Status ResolveEnumType(const string& type_url, Enum* enum_type) {
+ string url_prefix, type_name;
+ if (!SplitTypeUrl(type_url, &url_prefix, &type_name) ||
+ url_prefix != url_prefix_) {
+ return Status(INVALID_ARGUMENT, "Failed to parse type url: " + type_url);
+ }
+ if (url_prefix != url_prefix_) {
+ return Status(INVALID_ARGUMENT,
+ "Cannot resolve types from URL: " + url_prefix);
+ }
+ const EnumDescriptor* descriptor = pool_->FindEnumTypeByName(type_name);
+ if (descriptor == NULL) {
+ return Status(NOT_FOUND, "Cannot found the type: " + type_name);
+ }
+ ConvertEnumDescriptor(descriptor, enum_type);
+ return Status();
+ }
+
+ private:
+ void ConvertDescriptor(const Descriptor* descriptor, Type* type) {
+ type->Clear();
+ type->set_name(descriptor->full_name());
+ for (int i = 0; i < descriptor->field_count(); ++i) {
+ const FieldDescriptor* field = descriptor->field(i);
+ if (field->type() == FieldDescriptor::TYPE_GROUP) {
+ // Group fields cannot be represented with Type. We discard them.
+ continue;
+ }
+ ConvertFieldDescriptor(descriptor->field(i), type->add_fields());
+ }
+ for (int i = 0; i < descriptor->oneof_decl_count(); ++i) {
+ type->add_oneofs(descriptor->oneof_decl(i)->name());
+ }
+ type->mutable_source_context()->set_file_name(descriptor->file()->name());
+ ConvertMessageOptions(descriptor->options(), type->mutable_options());
+ }
+
+ void ConvertMessageOptions(const MessageOptions& options,
+ RepeatedPtrField<Option>* output) {
+ if (options.map_entry()) {
+ Option* option = output->Add();
+ option->set_name("map_entry");
+ BoolValue value;
+ value.set_value(true);
+ option->mutable_value()->PackFrom(value);
+ }
+
+ // TODO(xiaofeng): Set other "options"?
+ }
+
+ void ConvertFieldDescriptor(const FieldDescriptor* descriptor, Field* field) {
+ field->set_kind(static_cast<Field::Kind>(descriptor->type()));
+ switch (descriptor->label()) {
+ case FieldDescriptor::LABEL_OPTIONAL:
+ field->set_cardinality(Field::CARDINALITY_OPTIONAL);
+ break;
+ case FieldDescriptor::LABEL_REPEATED:
+ field->set_cardinality(Field::CARDINALITY_REPEATED);
+ break;
+ case FieldDescriptor::LABEL_REQUIRED:
+ field->set_cardinality(Field::CARDINALITY_REQUIRED);
+ break;
+ }
+ field->set_number(descriptor->number());
+ field->set_name(descriptor->name());
+ if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE) {
+ field->set_type_url(GetTypeUrl(descriptor->message_type()));
+ } else if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
+ field->set_type_url(GetTypeUrl(descriptor->enum_type()));
+ }
+ if (descriptor->containing_oneof() != NULL) {
+ field->set_oneof_index(descriptor->containing_oneof()->index() + 1);
+ }
+ if (descriptor->is_packed()) {
+ field->set_packed(true);
+ }
+
+ // TODO(xiaofeng): Set other field "options"?
+ }
+
+ void ConvertEnumDescriptor(const EnumDescriptor* descriptor,
+ Enum* enum_type) {
+ enum_type->Clear();
+ enum_type->set_name(descriptor->full_name());
+ enum_type->mutable_source_context()->set_file_name(
+ descriptor->file()->name());
+ for (int i = 0; i < descriptor->value_count(); ++i) {
+ const EnumValueDescriptor* value_descriptor = descriptor->value(i);
+ EnumValue* value =
+ enum_type->mutable_enumvalue()->Add();
+ value->set_name(value_descriptor->name());
+ value->set_number(value_descriptor->number());
+
+ // TODO(xiaofeng): Set EnumValue options.
+ }
+ // TODO(xiaofeng): Set Enum "options".
+ }
+
+ string GetTypeUrl(const Descriptor* descriptor) {
+ return url_prefix_ + "/" + descriptor->full_name();
+ }
+
+ string GetTypeUrl(const EnumDescriptor* descriptor) {
+ return url_prefix_ + "/" + descriptor->full_name();
+ }
+
+ string url_prefix_;
+ const DescriptorPool* pool_;
+};
+
+} // namespace
+
+TypeResolver* NewTypeResolverForDescriptorPool(
+ const string& url_prefix, const DescriptorPool* pool) {
+ return new DescriptorPoolTypeResolver(url_prefix, pool);
+}
+
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/util/type_resolver_util.h b/src/google/protobuf/util/type_resolver_util.h
new file mode 100644
index 00000000..c0ef3c1a
--- /dev/null
+++ b/src/google/protobuf/util/type_resolver_util.h
@@ -0,0 +1,52 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__
+#define GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+namespace google {
+namespace protobuf {
+class DescriptorPool;
+namespace util {
+class TypeResolver;
+
+// Creates a TypeResolver that serves type information in the given descriptor
+// pool. Caller takes ownership of the returned TypeResolver.
+LIBPROTOBUF_EXPORT TypeResolver* NewTypeResolverForDescriptorPool(
+ const string& url_prefix, const DescriptorPool* pool);
+
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__
diff --git a/src/google/protobuf/util/type_resolver_util_test.cc b/src/google/protobuf/util/type_resolver_util_test.cc
new file mode 100644
index 00000000..74b2d0da
--- /dev/null
+++ b/src/google/protobuf/util/type_resolver_util_test.cc
@@ -0,0 +1,338 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/type_resolver_util.h>
+
+#include <limits>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <string>
+#include <vector>
+
+#include <google/protobuf/type.pb.h>
+#include <google/protobuf/wrappers.pb.h>
+#include <google/protobuf/map_unittest.pb.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace util {
+namespace {
+using google::protobuf::Type;
+using google::protobuf::Enum;
+using google::protobuf::Field;
+using google::protobuf::Option;
+using google::protobuf::BoolValue;
+
+static const char kUrlPrefix[] = "type.googleapis.com";
+
+class DescriptorPoolTypeResolverTest : public testing::Test {
+ public:
+ DescriptorPoolTypeResolverTest() {
+ resolver_.reset(NewTypeResolverForDescriptorPool(
+ kUrlPrefix, DescriptorPool::generated_pool()));
+ }
+
+ const Field* FindField(const Type& type, const string& name) {
+ for (int i = 0; i < type.fields_size(); ++i) {
+ const Field& field = type.fields(i);
+ if (field.name() == name) {
+ return &field;
+ }
+ }
+ return NULL;
+ }
+
+ bool HasField(const Type& type, const string& name) {
+ return FindField(type, name) != NULL;
+ }
+
+ bool HasField(const Type& type, Field::Cardinality cardinality,
+ Field::Kind kind, const string& name, int number) {
+ const Field* field = FindField(type, name);
+ if (field == NULL) {
+ return false;
+ }
+ return field->cardinality() == cardinality &&
+ field->kind() == kind && field->number() == number;
+ }
+
+ bool CheckFieldTypeUrl(const Type& type, const string& name,
+ const string& type_url) {
+ const Field* field = FindField(type, name);
+ if (field == NULL) {
+ return false;
+ }
+ return field->type_url() == type_url;
+ }
+
+ bool FieldInOneof(const Type& type, const string& name,
+ const string& oneof_name) {
+ const Field* field = FindField(type, name);
+ if (field == NULL || field->oneof_index() <= 0 ||
+ field->oneof_index() > type.oneofs_size()) {
+ return false;
+ }
+ return type.oneofs(field->oneof_index() - 1) == oneof_name;
+ }
+
+ bool IsPacked(const Type& type, const string& name) {
+ const Field* field = FindField(type, name);
+ if (field == NULL) {
+ return false;
+ }
+ return field->packed();
+ }
+
+ bool EnumHasValue(const Enum& type, const string& name, int number) {
+ for (int i = 0; i < type.enumvalue_size(); ++i) {
+ if (type.enumvalue(i).name() == name &&
+ type.enumvalue(i).number() == number) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool HasBoolOption(const RepeatedPtrField<Option>& options,
+ const string& name, bool value) {
+ for (int i = 0; i < options.size(); ++i) {
+ const Option& option = options.Get(i);
+ if (option.name() == name) {
+ BoolValue bool_value;
+ if (option.value().UnpackTo(&bool_value) &&
+ bool_value.value() == value) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ string GetTypeUrl(string full_name) {
+ return kUrlPrefix + string("/") + full_name;
+ }
+
+ template<typename T>
+ string GetTypeUrl() {
+ return GetTypeUrl(T::descriptor()->full_name());
+ }
+
+ protected:
+ google::protobuf::scoped_ptr<TypeResolver> resolver_;
+};
+
+TEST_F(DescriptorPoolTypeResolverTest, TestAllTypes) {
+ Type type;
+ ASSERT_TRUE(resolver_->ResolveMessageType(
+ GetTypeUrl<protobuf_unittest::TestAllTypes>(), &type).ok());
+ // Check all optional fields.
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_INT32, "optional_int32", 1));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_INT64, "optional_int64", 2));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_UINT32, "optional_uint32", 3));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_UINT64, "optional_uint64", 4));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_SINT32, "optional_sint32", 5));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_SINT64, "optional_sint64", 6));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_FIXED32, "optional_fixed32", 7));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_FIXED64, "optional_fixed64", 8));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_SFIXED32, "optional_sfixed32", 9));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_SFIXED64, "optional_sfixed64", 10));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_FLOAT, "optional_float", 11));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_DOUBLE, "optional_double", 12));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_BOOL, "optional_bool", 13));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_STRING, "optional_string", 14));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_BYTES, "optional_bytes", 15));
+
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_MESSAGE, "optional_nested_message", 18));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_MESSAGE, "optional_foreign_message", 19));
+
+ EXPECT_TRUE(CheckFieldTypeUrl(
+ type, "optional_nested_message",
+ GetTypeUrl<protobuf_unittest::TestAllTypes::NestedMessage>()));
+ EXPECT_TRUE(CheckFieldTypeUrl(
+ type, "optional_foreign_message",
+ GetTypeUrl<protobuf_unittest::ForeignMessage>()));
+
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_ENUM, "optional_nested_enum", 21));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_ENUM, "optional_foreign_enum", 22));
+
+ EXPECT_TRUE(CheckFieldTypeUrl(
+ type, "optional_nested_enum",
+ GetTypeUrl("protobuf_unittest.TestAllTypes.NestedEnum")));
+ EXPECT_TRUE(CheckFieldTypeUrl(
+ type, "optional_foreign_enum",
+ GetTypeUrl("protobuf_unittest.ForeignEnum")));
+
+ // Check all repeated fields.
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_INT32, "repeated_int32", 31));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_INT64, "repeated_int64", 32));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_UINT32, "repeated_uint32", 33));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_UINT64, "repeated_uint64", 34));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_SINT32, "repeated_sint32", 35));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_SINT64, "repeated_sint64", 36));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_FIXED32, "repeated_fixed32", 37));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_FIXED64, "repeated_fixed64", 38));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_SFIXED32, "repeated_sfixed32", 39));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_SFIXED64, "repeated_sfixed64", 40));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_FLOAT, "repeated_float", 41));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_DOUBLE, "repeated_double", 42));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_BOOL, "repeated_bool", 43));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_STRING, "repeated_string", 44));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_BYTES, "repeated_bytes", 45));
+
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_MESSAGE, "repeated_nested_message", 48));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_MESSAGE, "repeated_foreign_message", 49));
+
+ EXPECT_TRUE(CheckFieldTypeUrl(
+ type, "repeated_nested_message",
+ GetTypeUrl<protobuf_unittest::TestAllTypes::NestedMessage>()));
+ EXPECT_TRUE(CheckFieldTypeUrl(
+ type, "repeated_foreign_message",
+ GetTypeUrl<protobuf_unittest::ForeignMessage>()));
+
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_ENUM, "repeated_nested_enum", 51));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_ENUM, "repeated_foreign_enum", 52));
+
+ EXPECT_TRUE(CheckFieldTypeUrl(
+ type, "repeated_nested_enum",
+ GetTypeUrl("protobuf_unittest.TestAllTypes.NestedEnum")));
+ EXPECT_TRUE(CheckFieldTypeUrl(
+ type, "repeated_foreign_enum",
+ GetTypeUrl("protobuf_unittest.ForeignEnum")));
+
+ // Groups are discarded when converting to Type.
+ const Descriptor* descriptor = protobuf_unittest::TestAllTypes::descriptor();
+ EXPECT_TRUE(descriptor->FindFieldByName("optionalgroup") != NULL);
+ EXPECT_TRUE(descriptor->FindFieldByName("repeatedgroup") != NULL);
+ ASSERT_FALSE(HasField(type, "optionalgroup"));
+ ASSERT_FALSE(HasField(type, "repeatedgroup"));
+}
+
+TEST_F(DescriptorPoolTypeResolverTest, TestPackedField) {
+ Type type;
+ ASSERT_TRUE(resolver_->ResolveMessageType(
+ GetTypeUrl<protobuf_unittest::TestPackedTypes>(), &type).ok());
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_INT32, "packed_int32", 90));
+ EXPECT_TRUE(IsPacked(type, "packed_int32"));
+}
+
+TEST_F(DescriptorPoolTypeResolverTest, TestOneof) {
+ Type type;
+ ASSERT_TRUE(resolver_->ResolveMessageType(
+ GetTypeUrl<protobuf_unittest::TestAllTypes>(), &type).ok());
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_UINT32, "oneof_uint32", 111));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_MESSAGE, "oneof_nested_message", 112));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_STRING, "oneof_string", 113));
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL,
+ Field::TYPE_BYTES, "oneof_bytes", 114));
+ EXPECT_TRUE(FieldInOneof(type, "oneof_uint32", "oneof_field"));
+ EXPECT_TRUE(FieldInOneof(type, "oneof_nested_message", "oneof_field"));
+ EXPECT_TRUE(FieldInOneof(type, "oneof_string", "oneof_field"));
+ EXPECT_TRUE(FieldInOneof(type, "oneof_bytes", "oneof_field"));
+}
+
+TEST_F(DescriptorPoolTypeResolverTest, TestMap) {
+ Type type;
+ ASSERT_TRUE(resolver_->ResolveMessageType(
+ GetTypeUrl<protobuf_unittest::TestMap>(), &type).ok());
+ EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED,
+ Field::TYPE_MESSAGE, "map_int32_int32", 1));
+ EXPECT_TRUE(CheckFieldTypeUrl(
+ type, "map_int32_int32",
+ GetTypeUrl("protobuf_unittest.TestMap.MapInt32Int32Entry")));
+
+ ASSERT_TRUE(resolver_->ResolveMessageType(
+ GetTypeUrl("protobuf_unittest.TestMap.MapInt32Int32Entry"),
+ &type).ok());
+ EXPECT_TRUE(HasBoolOption(type.options(), "map_entry", true));
+}
+
+TEST_F(DescriptorPoolTypeResolverTest, TestEnum) {
+ Enum type;
+ ASSERT_TRUE(resolver_->ResolveEnumType(
+ GetTypeUrl("protobuf_unittest.TestAllTypes.NestedEnum"), &type).ok());
+ EnumHasValue(type, "FOO", 1);
+ EnumHasValue(type, "BAR", 2);
+ EnumHasValue(type, "BAZ", 3);
+ EnumHasValue(type, "NEG", -1);
+}
+
+} // namespace
+} // namespace util
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/well_known_types_unittest.cc b/src/google/protobuf/well_known_types_unittest.cc
new file mode 100644
index 00000000..c9a9aa10
--- /dev/null
+++ b/src/google/protobuf/well_known_types_unittest.cc
@@ -0,0 +1,60 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include <google/protobuf/unittest_well_known_types.pb.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+// This test only checks whether well-known types are included in protobuf
+// runtime library. The test passes if it compiles.
+TEST(WellKnownTypesTest, AllKnownTypesAreIncluded) {
+ protobuf_unittest::TestWellKnownTypes message;
+ EXPECT_EQ(0, message.any_field().ByteSize());
+ EXPECT_EQ(0, message.api_field().ByteSize());
+ EXPECT_EQ(0, message.duration_field().ByteSize());
+ EXPECT_EQ(0, message.empty_field().ByteSize());
+ EXPECT_EQ(0, message.field_mask_field().ByteSize());
+ EXPECT_EQ(0, message.source_context_field().ByteSize());
+ EXPECT_EQ(0, message.struct_field().ByteSize());
+ EXPECT_EQ(0, message.timestamp_field().ByteSize());
+ EXPECT_EQ(0, message.type_field().ByteSize());
+ EXPECT_EQ(0, message.int32_field().ByteSize());
+}
+
+} // namespace
+
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index f4f02157..c5db963b 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -54,15 +54,6 @@ namespace google {
namespace protobuf {
namespace internal {
-namespace {
-
-// This function turns out to be convenient when using some macros later.
-inline int GetEnumNumber(const EnumValueDescriptor* descriptor) {
- return descriptor->number();
-}
-
-} // anonymous namespace
-
// ===================================================================
bool UnknownFieldSetFieldSkipper::SkipField(
@@ -141,7 +132,7 @@ bool WireFormat::SkipField(io::CodedInputStream* input, uint32 tag,
bool WireFormat::SkipMessage(io::CodedInputStream* input,
UnknownFieldSet* unknown_fields) {
- while(true) {
+ while (true) {
uint32 tag = input->ReadTag();
if (tag == 0) {
// End of input. This is a valid place to end, so return true.
@@ -159,6 +150,31 @@ bool WireFormat::SkipMessage(io::CodedInputStream* input,
}
}
+bool WireFormat::ReadPackedEnumPreserveUnknowns(io::CodedInputStream* input,
+ uint32 field_number,
+ bool (*is_valid)(int),
+ UnknownFieldSet* unknown_fields,
+ RepeatedField<int>* values) {
+ uint32 length;
+ if (!input->ReadVarint32(&length)) return false;
+ io::CodedInputStream::Limit limit = input->PushLimit(length);
+ while (input->BytesUntilLimit() > 0) {
+ int value;
+ if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, WireFormatLite::TYPE_ENUM>(input, &value)) {
+ return false;
+ }
+ if (is_valid == NULL || is_valid(value)) {
+ values->Add(value);
+ } else {
+ unknown_fields->AddVarint(field_number, value);
+ }
+ }
+ input->PopLimit(limit);
+ return true;
+}
+
+
void WireFormat::SerializeUnknownFields(const UnknownFieldSet& unknown_fields,
io::CodedOutputStream* output) {
for (int i = 0; i < unknown_fields.field_count(); i++) {
@@ -520,6 +536,14 @@ bool WireFormat::ParseAndMergeField(
field->enum_type()->FindValueByNumber(value);
if (enum_value != NULL) {
message_reflection->AddEnum(message, field, enum_value);
+ } else {
+ // The enum value is not one of the known values. Add it to the
+ // UnknownFieldSet.
+ int64 sign_extended_value = static_cast<int64>(value);
+ message_reflection->MutableUnknownFields(message)
+ ->AddVarint(
+ WireFormatLite::GetTagFieldNumber(tag),
+ sign_extended_value);
}
}
}
@@ -796,7 +820,7 @@ void WireFormat::SerializeFieldWithCachedSizes(
count = 1;
}
- const bool is_packed = field->options().packed();
+ const bool is_packed = field->is_packed();
if (is_packed && count > 0) {
WireFormatLite::WriteTag(field->number(),
WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
@@ -963,7 +987,7 @@ int WireFormat::FieldByteSize(
const int data_size = FieldDataOnlyByteSize(field, message);
int our_size = data_size;
- if (field->options().packed()) {
+ if (field->is_packed()) {
if (data_size > 0) {
// Packed fields get serialized like a string, not their native type.
// Technically this doesn't really matter; the size only changes if it's
diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h
index 9f26eb29..84270fee 100644
--- a/src/google/protobuf/wire_format.h
+++ b/src/google/protobuf/wire_format.h
@@ -138,6 +138,14 @@ class LIBPROTOBUF_EXPORT WireFormat {
static bool SkipMessage(io::CodedInputStream* input,
UnknownFieldSet* unknown_fields);
+ // Read a packed enum field. If the is_valid function is not NULL, values for
+ // which is_valid(value) returns false are appended to unknown_fields_stream.
+ static bool ReadPackedEnumPreserveUnknowns(io::CodedInputStream* input,
+ uint32 field_number,
+ bool (*is_valid)(int),
+ UnknownFieldSet* unknown_fields,
+ RepeatedField<int>* values);
+
// Write the contents of an UnknownFieldSet to the output.
static void SerializeUnknownFields(const UnknownFieldSet& unknown_fields,
io::CodedOutputStream* output);
@@ -282,7 +290,7 @@ class LIBPROTOBUF_EXPORT UnknownFieldSetFieldSkipper : public FieldSkipper {
inline WireFormatLite::WireType WireFormat::WireTypeForField(
const FieldDescriptor* field) {
- if (field->options().packed()) {
+ if (field->is_packed()) {
return WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
} else {
return WireTypeForFieldType(field->type());
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index 50616551..2ce4920c 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -304,6 +304,34 @@ bool WireFormatLite::ReadPackedEnumNoInline(io::CodedInputStream* input,
return true;
}
+bool WireFormatLite::ReadPackedEnumPreserveUnknowns(
+ io::CodedInputStream* input,
+ int field_number,
+ bool (*is_valid)(int),
+ io::CodedOutputStream* unknown_fields_stream,
+ RepeatedField<int>* values) {
+ uint32 length;
+ if (!input->ReadVarint32(&length)) return false;
+ io::CodedInputStream::Limit limit = input->PushLimit(length);
+ while (input->BytesUntilLimit() > 0) {
+ int value;
+ if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, WireFormatLite::TYPE_ENUM>(input, &value)) {
+ return false;
+ }
+ if (is_valid == NULL || is_valid(value)) {
+ values->Add(value);
+ } else {
+ uint32 tag = WireFormatLite::MakeTag(field_number,
+ WireFormatLite::WIRETYPE_VARINT);
+ unknown_fields_stream->WriteVarint32(tag);
+ unknown_fields_stream->WriteVarint32(value);
+ }
+ }
+ input->PopLimit(limit);
+ return true;
+}
+
void WireFormatLite::WriteInt32(int field_number, int32 value,
io::CodedOutputStream* output) {
WriteTag(field_number, WIRETYPE_VARINT, output);
diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h
index acf88ead..ac83abdc 100644
--- a/src/google/protobuf/wire_format_lite.h
+++ b/src/google/protobuf/wire_format_lite.h
@@ -291,11 +291,20 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
template <typename CType, enum FieldType DeclaredType>
static bool ReadPackedPrimitiveNoInline(input, RepeatedField<CType>* value);
- // Read a packed enum field. Values for which is_valid() returns false are
- // dropped. If is_valid == NULL, no values are dropped.
+ // Read a packed enum field. If the is_valid function is not NULL, values for
+ // which is_valid(value) returns false are silently dropped.
static bool ReadPackedEnumNoInline(input,
bool (*is_valid)(int),
- RepeatedField<int>* value);
+ RepeatedField<int>* values);
+
+ // Read a packed enum field. If the is_valid function is not NULL, values for
+ // which is_valid(value) returns false are appended to unknown_fields_stream.
+ static bool ReadPackedEnumPreserveUnknowns(
+ input,
+ field_number,
+ bool (*is_valid)(int),
+ io::CodedOutputStream* unknown_fields_stream,
+ RepeatedField<int>* values);
// Read a string. ReadString(..., string* value) requires an existing string.
static inline bool ReadString(input, string* value);
@@ -321,6 +330,17 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
template<typename MessageType>
static inline bool ReadMessageNoVirtual(input, MessageType* value);
+ // The same, but do not modify input's recursion depth. This is useful
+ // when reading a bunch of groups or messages in a loop, because then the
+ // recursion depth can be incremented before the loop and decremented after.
+ template<typename MessageType>
+ static inline bool ReadGroupNoVirtualNoRecursionDepth(field_number, input,
+ MessageType* value);
+
+ template<typename MessageType>
+ static inline bool ReadMessageNoVirtualNoRecursionDepth(input,
+ MessageType* value);
+
// Write a tag. The Write*() functions typically include the tag, so
// normally there's no need to call this unless using the Write*NoTag()
// variants.
@@ -647,7 +667,7 @@ inline double WireFormatLite::DecodeDouble(uint64 value) {
inline uint32 WireFormatLite::ZigZagEncode32(int32 n) {
// Note: the right-shift must be arithmetic
- return (n << 1) ^ (n >> 31);
+ return (static_cast<uint32>(n) << 1) ^ (n >> 31);
}
inline int32 WireFormatLite::ZigZagDecode32(uint32 n) {
@@ -656,7 +676,7 @@ inline int32 WireFormatLite::ZigZagDecode32(uint32 n) {
inline uint64 WireFormatLite::ZigZagEncode64(int64 n) {
// Note: the right-shift must be arithmetic
- return (n << 1) ^ (n >> 63);
+ return (static_cast<uint64>(n) << 1) ^ (n >> 63);
}
inline int64 WireFormatLite::ZigZagDecode64(uint64 n) {
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
index 129fc63f..d073ff92 100644
--- a/src/google/protobuf/wire_format_lite_inl.h
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -470,7 +470,7 @@ inline bool WireFormatLite::ReadGroupNoVirtual(
if (!value->
MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input))
return false;
- input->DecrementRecursionDepth();
+ input->UnsafeDecrementRecursionDepth();
// Make sure the last thing read was an end tag for this group.
if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) {
return false;
@@ -478,6 +478,14 @@ inline bool WireFormatLite::ReadGroupNoVirtual(
return true;
}
template<typename MessageType_WorkAroundCppLookupDefect>
+inline bool WireFormatLite::ReadGroupNoVirtualNoRecursionDepth(
+ int field_number, io::CodedInputStream* input,
+ MessageType_WorkAroundCppLookupDefect* value) {
+ return value->MessageType_WorkAroundCppLookupDefect::
+ MergePartialFromCodedStream(input) &&
+ input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP));
+}
+template<typename MessageType_WorkAroundCppLookupDefect>
inline bool WireFormatLite::ReadMessageNoVirtual(
io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) {
uint32 length;
@@ -491,6 +499,17 @@ inline bool WireFormatLite::ReadMessageNoVirtual(
// tag.
return input->DecrementRecursionDepthAndPopLimit(p.first);
}
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline bool WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) {
+ io::CodedInputStream::Limit old_limit = input->ReadLengthAndPushLimit();
+ if (!value->
+ MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input))
+ return false;
+ // Make sure that parsing stopped when the limit was hit, not at an endgroup
+ // tag.
+ return input->CheckEntireMessageConsumedAndPopLimit(old_limit);
+}
// ===================================================================
diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc
index a3062a6a..aef22b29 100644
--- a/src/google/protobuf/wire_format_unittest.cc
+++ b/src/google/protobuf/wire_format_unittest.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_proto3_arena.pb.h>
#include <google/protobuf/unittest_mset.pb.h>
#include <google/protobuf/test_util.h>
@@ -767,7 +768,7 @@ TEST(WireFormatTest, RepeatedScalarsDifferentTagSizes) {
}
TEST(WireFormatTest, CompatibleTypes) {
- const int64 data = 0x100000000;
+ const int64 data = 0x100000000LL;
unittest::Int64Message msg1;
msg1.set_data(data);
string serialized;
@@ -794,6 +795,169 @@ TEST(WireFormatTest, CompatibleTypes) {
ASSERT_EQ(static_cast<uint32>(data), msg5.data());
}
+class Proto3PrimitiveRepeatedWireFormatTest : public ::testing::Test {
+ protected:
+ Proto3PrimitiveRepeatedWireFormatTest()
+ : packedTestAllTypes_(
+ "\xFA\x01\x01\x01"
+ "\x82\x02\x01\x01"
+ "\x8A\x02\x01\x01"
+ "\x92\x02\x01\x01"
+ "\x9A\x02\x01\x02"
+ "\xA2\x02\x01\x02"
+ "\xAA\x02\x04\x01\x00\x00\x00"
+ "\xB2\x02\x08\x01\x00\x00\x00\x00\x00\x00\x00"
+ "\xBA\x02\x04\x01\x00\x00\x00"
+ "\xC2\x02\x08\x01\x00\x00\x00\x00\x00\x00\x00"
+ "\xCA\x02\x04\x00\x00\x80\x3f"
+ "\xD2\x02\x08\x00\x00\x00\x00\x00\x00\xf0\x3f"
+ "\xDA\x02\x01\x01"
+ "\x9A\x03\x01\x01",
+ 86),
+ packedTestUnpackedTypes_(
+ "\x0A\x01\x01"
+ "\x12\x01\x01"
+ "\x1A\x01\x01"
+ "\x22\x01\x01"
+ "\x2A\x01\x02"
+ "\x32\x01\x02"
+ "\x3A\x04\x01\x00\x00\x00"
+ "\x42\x08\x01\x00\x00\x00\x00\x00\x00\x00"
+ "\x4A\x04\x01\x00\x00\x00"
+ "\x52\x08\x01\x00\x00\x00\x00\x00\x00\x00"
+ "\x5A\x04\x00\x00\x80\x3f"
+ "\x62\x08\x00\x00\x00\x00\x00\x00\xf0\x3f"
+ "\x6A\x01\x01"
+ "\x72\x01\x01",
+ 72),
+ unpackedTestAllTypes_(
+ "\xF8\x01\x01"
+ "\x80\x02\x01"
+ "\x88\x02\x01"
+ "\x90\x02\x01"
+ "\x98\x02\x02"
+ "\xA0\x02\x02"
+ "\xAD\x02\x01\x00\x00\x00"
+ "\xB1\x02\x01\x00\x00\x00\x00\x00\x00\x00"
+ "\xBD\x02\x01\x00\x00\x00"
+ "\xC1\x02\x01\x00\x00\x00\x00\x00\x00\x00"
+ "\xCD\x02\x00\x00\x80\x3f"
+ "\xD1\x02\x00\x00\x00\x00\x00\x00\xf0\x3f"
+ "\xD8\x02\x01"
+ "\x98\x03\x01",
+ 72),
+ unpackedTestUnpackedTypes_(
+ "\x08\x01"
+ "\x10\x01"
+ "\x18\x01"
+ "\x20\x01"
+ "\x28\x02"
+ "\x30\x02"
+ "\x3D\x01\x00\x00\x00"
+ "\x41\x01\x00\x00\x00\x00\x00\x00\x00"
+ "\x4D\x01\x00\x00\x00"
+ "\x51\x01\x00\x00\x00\x00\x00\x00\x00"
+ "\x5D\x00\x00\x80\x3f"
+ "\x61\x00\x00\x00\x00\x00\x00\xf0\x3f"
+ "\x68\x01"
+ "\x70\x01",
+ 58) {}
+ template <class Proto>
+ void SetProto3PrimitiveRepeatedFields(Proto* message) {
+ message->add_repeated_int32(1);
+ message->add_repeated_int64(1);
+ message->add_repeated_uint32(1);
+ message->add_repeated_uint64(1);
+ message->add_repeated_sint32(1);
+ message->add_repeated_sint64(1);
+ message->add_repeated_fixed32(1);
+ message->add_repeated_fixed64(1);
+ message->add_repeated_sfixed32(1);
+ message->add_repeated_sfixed64(1);
+ message->add_repeated_float(1.0);
+ message->add_repeated_double(1.0);
+ message->add_repeated_bool(true);
+ message->add_repeated_nested_enum(
+ proto3_arena_unittest::TestAllTypes_NestedEnum_FOO);
+ }
+
+ template <class Proto>
+ void ExpectProto3PrimitiveRepeatedFieldsSet(const Proto& message) {
+ EXPECT_EQ(1, message.repeated_int32(0));
+ EXPECT_EQ(1, message.repeated_int64(0));
+ EXPECT_EQ(1, message.repeated_uint32(0));
+ EXPECT_EQ(1, message.repeated_uint64(0));
+ EXPECT_EQ(1, message.repeated_sint32(0));
+ EXPECT_EQ(1, message.repeated_sint64(0));
+ EXPECT_EQ(1, message.repeated_fixed32(0));
+ EXPECT_EQ(1, message.repeated_fixed64(0));
+ EXPECT_EQ(1, message.repeated_sfixed32(0));
+ EXPECT_EQ(1, message.repeated_sfixed64(0));
+ EXPECT_EQ(1.0, message.repeated_float(0));
+ EXPECT_EQ(1.0, message.repeated_double(0));
+ EXPECT_EQ(true, message.repeated_bool(0));
+ EXPECT_EQ(proto3_arena_unittest::TestAllTypes_NestedEnum_FOO,
+ message.repeated_nested_enum(0));
+ }
+
+ template <class Proto>
+ void TestSerialization(Proto* message, const string& expected) {
+ SetProto3PrimitiveRepeatedFields(message);
+
+ int size = message->ByteSize();
+
+ // Serialize using the generated code.
+ string generated_data;
+ {
+ io::StringOutputStream raw_output(&generated_data);
+ io::CodedOutputStream output(&raw_output);
+ message->SerializeWithCachedSizes(&output);
+ ASSERT_FALSE(output.HadError());
+ }
+ EXPECT_TRUE(expected == generated_data);
+
+ // Serialize using the dynamic code.
+ string dynamic_data;
+ {
+ io::StringOutputStream raw_output(&dynamic_data);
+ io::CodedOutputStream output(&raw_output);
+ WireFormat::SerializeWithCachedSizes(*message, size, &output);
+ ASSERT_FALSE(output.HadError());
+ }
+ EXPECT_TRUE(expected == dynamic_data);
+ }
+
+ template <class Proto>
+ void TestParsing(Proto* message, const string& compatible_data) {
+ message->Clear();
+ message->ParseFromString(compatible_data);
+ ExpectProto3PrimitiveRepeatedFieldsSet(*message);
+
+ message->Clear();
+ io::CodedInputStream input(
+ reinterpret_cast<const uint8*>(compatible_data.data()),
+ compatible_data.size());
+ WireFormat::ParseAndMergePartial(&input, message);
+ ExpectProto3PrimitiveRepeatedFieldsSet(*message);
+ }
+
+ const string packedTestAllTypes_;
+ const string packedTestUnpackedTypes_;
+ const string unpackedTestAllTypes_;
+ const string unpackedTestUnpackedTypes_;
+};
+
+TEST_F(Proto3PrimitiveRepeatedWireFormatTest, Proto3PrimitiveRepeated) {
+ proto3_arena_unittest::TestAllTypes packed_message;
+ proto3_arena_unittest::TestUnpackedTypes unpacked_message;
+ TestSerialization(&packed_message, packedTestAllTypes_);
+ TestParsing(&packed_message, packedTestAllTypes_);
+ TestParsing(&packed_message, unpackedTestAllTypes_);
+ TestSerialization(&unpacked_message, unpackedTestUnpackedTypes_);
+ TestParsing(&unpacked_message, packedTestUnpackedTypes_);
+ TestParsing(&unpacked_message, unpackedTestUnpackedTypes_);
+}
+
class WireFormatInvalidInputTest : public testing::Test {
protected:
// Make a serialized TestAllTypes in which the field optional_nested_message
diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc
new file mode 100644
index 00000000..db75db15
--- /dev/null
+++ b/src/google/protobuf/wrappers.pb.cc
@@ -0,0 +1,2419 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/wrappers.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "google/protobuf/wrappers.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+namespace {
+
+const ::google::protobuf::Descriptor* DoubleValue_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ DoubleValue_reflection_ = NULL;
+const ::google::protobuf::Descriptor* FloatValue_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ FloatValue_reflection_ = NULL;
+const ::google::protobuf::Descriptor* Int64Value_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ Int64Value_reflection_ = NULL;
+const ::google::protobuf::Descriptor* UInt64Value_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ UInt64Value_reflection_ = NULL;
+const ::google::protobuf::Descriptor* Int32Value_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ Int32Value_reflection_ = NULL;
+const ::google::protobuf::Descriptor* UInt32Value_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ UInt32Value_reflection_ = NULL;
+const ::google::protobuf::Descriptor* BoolValue_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ BoolValue_reflection_ = NULL;
+const ::google::protobuf::Descriptor* StringValue_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ StringValue_reflection_ = NULL;
+const ::google::protobuf::Descriptor* BytesValue_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ BytesValue_reflection_ = NULL;
+
+} // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ const ::google::protobuf::FileDescriptor* file =
+ ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+ "google/protobuf/wrappers.proto");
+ GOOGLE_CHECK(file != NULL);
+ DoubleValue_descriptor_ = file->message_type(0);
+ static const int DoubleValue_offsets_[1] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DoubleValue, value_),
+ };
+ DoubleValue_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ DoubleValue_descriptor_,
+ DoubleValue::default_instance_,
+ DoubleValue_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(DoubleValue),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DoubleValue, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DoubleValue, _is_default_instance_));
+ FloatValue_descriptor_ = file->message_type(1);
+ static const int FloatValue_offsets_[1] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FloatValue, value_),
+ };
+ FloatValue_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ FloatValue_descriptor_,
+ FloatValue::default_instance_,
+ FloatValue_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(FloatValue),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FloatValue, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FloatValue, _is_default_instance_));
+ Int64Value_descriptor_ = file->message_type(2);
+ static const int Int64Value_offsets_[1] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Int64Value, value_),
+ };
+ Int64Value_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ Int64Value_descriptor_,
+ Int64Value::default_instance_,
+ Int64Value_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(Int64Value),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Int64Value, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Int64Value, _is_default_instance_));
+ UInt64Value_descriptor_ = file->message_type(3);
+ static const int UInt64Value_offsets_[1] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UInt64Value, value_),
+ };
+ UInt64Value_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ UInt64Value_descriptor_,
+ UInt64Value::default_instance_,
+ UInt64Value_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(UInt64Value),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UInt64Value, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UInt64Value, _is_default_instance_));
+ Int32Value_descriptor_ = file->message_type(4);
+ static const int Int32Value_offsets_[1] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Int32Value, value_),
+ };
+ Int32Value_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ Int32Value_descriptor_,
+ Int32Value::default_instance_,
+ Int32Value_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(Int32Value),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Int32Value, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Int32Value, _is_default_instance_));
+ UInt32Value_descriptor_ = file->message_type(5);
+ static const int UInt32Value_offsets_[1] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UInt32Value, value_),
+ };
+ UInt32Value_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ UInt32Value_descriptor_,
+ UInt32Value::default_instance_,
+ UInt32Value_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(UInt32Value),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UInt32Value, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UInt32Value, _is_default_instance_));
+ BoolValue_descriptor_ = file->message_type(6);
+ static const int BoolValue_offsets_[1] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BoolValue, value_),
+ };
+ BoolValue_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ BoolValue_descriptor_,
+ BoolValue::default_instance_,
+ BoolValue_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(BoolValue),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BoolValue, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BoolValue, _is_default_instance_));
+ StringValue_descriptor_ = file->message_type(7);
+ static const int StringValue_offsets_[1] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(StringValue, value_),
+ };
+ StringValue_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ StringValue_descriptor_,
+ StringValue::default_instance_,
+ StringValue_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(StringValue),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(StringValue, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(StringValue, _is_default_instance_));
+ BytesValue_descriptor_ = file->message_type(8);
+ static const int BytesValue_offsets_[1] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BytesValue, value_),
+ };
+ BytesValue_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ BytesValue_descriptor_,
+ BytesValue::default_instance_,
+ BytesValue_offsets_,
+ -1,
+ -1,
+ -1,
+ sizeof(BytesValue),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BytesValue, _internal_metadata_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BytesValue, _is_default_instance_));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+ ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+ &protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ DoubleValue_descriptor_, &DoubleValue::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ FloatValue_descriptor_, &FloatValue::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ Int64Value_descriptor_, &Int64Value::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ UInt64Value_descriptor_, &UInt64Value::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ Int32Value_descriptor_, &Int32Value::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ UInt32Value_descriptor_, &UInt32Value::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ BoolValue_descriptor_, &BoolValue::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ StringValue_descriptor_, &StringValue::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ BytesValue_descriptor_, &BytesValue::default_instance());
+}
+
+} // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto() {
+ delete DoubleValue::default_instance_;
+ delete DoubleValue_reflection_;
+ delete FloatValue::default_instance_;
+ delete FloatValue_reflection_;
+ delete Int64Value::default_instance_;
+ delete Int64Value_reflection_;
+ delete UInt64Value::default_instance_;
+ delete UInt64Value_reflection_;
+ delete Int32Value::default_instance_;
+ delete Int32Value_reflection_;
+ delete UInt32Value::default_instance_;
+ delete UInt32Value_reflection_;
+ delete BoolValue::default_instance_;
+ delete BoolValue_reflection_;
+ delete StringValue::default_instance_;
+ delete StringValue_reflection_;
+ delete BytesValue::default_instance_;
+ delete BytesValue_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto() {
+ static bool already_here = false;
+ if (already_here) return;
+ already_here = true;
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+ "\n\036google/protobuf/wrappers.proto\022\017google"
+ ".protobuf\"\034\n\013DoubleValue\022\r\n\005value\030\001 \001(\001\""
+ "\033\n\nFloatValue\022\r\n\005value\030\001 \001(\002\"\033\n\nInt64Val"
+ "ue\022\r\n\005value\030\001 \001(\003\"\034\n\013UInt64Value\022\r\n\005valu"
+ "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(\014BM\n\023com"
+ ".google.protobufB\rWrappersProtoP\001\242\002\003GPB\252"
+ "\002\036Google.Protobuf.WellKnownTypesb\006proto3", 400);
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+ "google/protobuf/wrappers.proto", &protobuf_RegisterTypes);
+ DoubleValue::default_instance_ = new DoubleValue();
+ FloatValue::default_instance_ = new FloatValue();
+ Int64Value::default_instance_ = new Int64Value();
+ UInt64Value::default_instance_ = new UInt64Value();
+ Int32Value::default_instance_ = new Int32Value();
+ UInt32Value::default_instance_ = new UInt32Value();
+ BoolValue::default_instance_ = new BoolValue();
+ StringValue::default_instance_ = new StringValue();
+ BytesValue::default_instance_ = new BytesValue();
+ DoubleValue::default_instance_->InitAsDefaultInstance();
+ FloatValue::default_instance_->InitAsDefaultInstance();
+ Int64Value::default_instance_->InitAsDefaultInstance();
+ UInt64Value::default_instance_->InitAsDefaultInstance();
+ Int32Value::default_instance_->InitAsDefaultInstance();
+ UInt32Value::default_instance_->InitAsDefaultInstance();
+ BoolValue::default_instance_->InitAsDefaultInstance();
+ StringValue::default_instance_->InitAsDefaultInstance();
+ BytesValue::default_instance_->InitAsDefaultInstance();
+ ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fwrappers_2eproto {
+ StaticDescriptorInitializer_google_2fprotobuf_2fwrappers_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ }
+} static_descriptor_initializer_google_2fprotobuf_2fwrappers_2eproto_;
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+static void MergeFromFail(int line) {
+ GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+} // namespace
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int DoubleValue::kValueFieldNumber;
+#endif // !_MSC_VER
+
+DoubleValue::DoubleValue()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.DoubleValue)
+}
+
+void DoubleValue::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+DoubleValue::DoubleValue(const DoubleValue& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.DoubleValue)
+}
+
+void DoubleValue::SharedCtor() {
+ _is_default_instance_ = false;
+ _cached_size_ = 0;
+ value_ = 0;
+}
+
+DoubleValue::~DoubleValue() {
+ // @@protoc_insertion_point(destructor:google.protobuf.DoubleValue)
+ SharedDtor();
+}
+
+void DoubleValue::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void DoubleValue::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* DoubleValue::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return DoubleValue_descriptor_;
+}
+
+const DoubleValue& DoubleValue::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ return *default_instance_;
+}
+
+DoubleValue* DoubleValue::default_instance_ = NULL;
+
+DoubleValue* DoubleValue::New(::google::protobuf::Arena* arena) const {
+ DoubleValue* n = new DoubleValue;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void DoubleValue::Clear() {
+ value_ = 0;
+}
+
+bool DoubleValue::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.DoubleValue)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional double value = 1;
+ case 1: {
+ if (tag == 9) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
+ input, &value_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.DoubleValue)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.DoubleValue)
+ return false;
+#undef DO_
+}
+
+void DoubleValue::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.DoubleValue)
+ // optional double value = 1;
+ if (this->value() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteDouble(1, this->value(), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.DoubleValue)
+}
+
+::google::protobuf::uint8* DoubleValue::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DoubleValue)
+ // optional double value = 1;
+ if (this->value() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(1, this->value(), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DoubleValue)
+ return target;
+}
+
+int DoubleValue::ByteSize() const {
+ int total_size = 0;
+
+ // optional double value = 1;
+ if (this->value() != 0) {
+ total_size += 1 + 8;
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void DoubleValue::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const DoubleValue* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const DoubleValue>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void DoubleValue::MergeFrom(const DoubleValue& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from.value() != 0) {
+ set_value(from.value());
+ }
+}
+
+void DoubleValue::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void DoubleValue::CopyFrom(const DoubleValue& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool DoubleValue::IsInitialized() const {
+
+ return true;
+}
+
+void DoubleValue::Swap(DoubleValue* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void DoubleValue::InternalSwap(DoubleValue* other) {
+ std::swap(value_, other->value_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata DoubleValue::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = DoubleValue_descriptor_;
+ metadata.reflection = DoubleValue_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// DoubleValue
+
+// optional double value = 1;
+void DoubleValue::clear_value() {
+ value_ = 0;
+}
+ double DoubleValue::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DoubleValue.value)
+ return value_;
+}
+ void DoubleValue::set_value(double value) {
+
+ value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.DoubleValue.value)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int FloatValue::kValueFieldNumber;
+#endif // !_MSC_VER
+
+FloatValue::FloatValue()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.FloatValue)
+}
+
+void FloatValue::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+FloatValue::FloatValue(const FloatValue& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.FloatValue)
+}
+
+void FloatValue::SharedCtor() {
+ _is_default_instance_ = false;
+ _cached_size_ = 0;
+ value_ = 0;
+}
+
+FloatValue::~FloatValue() {
+ // @@protoc_insertion_point(destructor:google.protobuf.FloatValue)
+ SharedDtor();
+}
+
+void FloatValue::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void FloatValue::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* FloatValue::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return FloatValue_descriptor_;
+}
+
+const FloatValue& FloatValue::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ return *default_instance_;
+}
+
+FloatValue* FloatValue::default_instance_ = NULL;
+
+FloatValue* FloatValue::New(::google::protobuf::Arena* arena) const {
+ FloatValue* n = new FloatValue;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void FloatValue::Clear() {
+ value_ = 0;
+}
+
+bool FloatValue::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.FloatValue)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional float value = 1;
+ case 1: {
+ if (tag == 13) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+ input, &value_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.FloatValue)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.FloatValue)
+ return false;
+#undef DO_
+}
+
+void FloatValue::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.FloatValue)
+ // optional float value = 1;
+ if (this->value() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteFloat(1, this->value(), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.FloatValue)
+}
+
+::google::protobuf::uint8* FloatValue::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FloatValue)
+ // optional float value = 1;
+ if (this->value() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(1, this->value(), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FloatValue)
+ return target;
+}
+
+int FloatValue::ByteSize() const {
+ int total_size = 0;
+
+ // optional float value = 1;
+ if (this->value() != 0) {
+ total_size += 1 + 4;
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void FloatValue::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const FloatValue* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const FloatValue>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void FloatValue::MergeFrom(const FloatValue& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from.value() != 0) {
+ set_value(from.value());
+ }
+}
+
+void FloatValue::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void FloatValue::CopyFrom(const FloatValue& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool FloatValue::IsInitialized() const {
+
+ return true;
+}
+
+void FloatValue::Swap(FloatValue* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void FloatValue::InternalSwap(FloatValue* other) {
+ std::swap(value_, other->value_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata FloatValue::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = FloatValue_descriptor_;
+ metadata.reflection = FloatValue_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FloatValue
+
+// optional float value = 1;
+void FloatValue::clear_value() {
+ value_ = 0;
+}
+ float FloatValue::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FloatValue.value)
+ return value_;
+}
+ void FloatValue::set_value(float value) {
+
+ value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FloatValue.value)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int Int64Value::kValueFieldNumber;
+#endif // !_MSC_VER
+
+Int64Value::Int64Value()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.Int64Value)
+}
+
+void Int64Value::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+Int64Value::Int64Value(const Int64Value& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.Int64Value)
+}
+
+void Int64Value::SharedCtor() {
+ _is_default_instance_ = false;
+ _cached_size_ = 0;
+ value_ = GOOGLE_LONGLONG(0);
+}
+
+Int64Value::~Int64Value() {
+ // @@protoc_insertion_point(destructor:google.protobuf.Int64Value)
+ SharedDtor();
+}
+
+void Int64Value::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void Int64Value::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Int64Value::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Int64Value_descriptor_;
+}
+
+const Int64Value& Int64Value::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ return *default_instance_;
+}
+
+Int64Value* Int64Value::default_instance_ = NULL;
+
+Int64Value* Int64Value::New(::google::protobuf::Arena* arena) const {
+ Int64Value* n = new Int64Value;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void Int64Value::Clear() {
+ value_ = GOOGLE_LONGLONG(0);
+}
+
+bool Int64Value::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.Int64Value)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional int64 value = 1;
+ case 1: {
+ if (tag == 8) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
+ input, &value_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.Int64Value)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.Int64Value)
+ return false;
+#undef DO_
+}
+
+void Int64Value::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.Int64Value)
+ // optional int64 value = 1;
+ if (this->value() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt64(1, this->value(), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.Int64Value)
+}
+
+::google::protobuf::uint8* Int64Value::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Int64Value)
+ // optional int64 value = 1;
+ if (this->value() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(1, this->value(), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Int64Value)
+ return target;
+}
+
+int Int64Value::ByteSize() const {
+ int total_size = 0;
+
+ // optional int64 value = 1;
+ if (this->value() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int64Size(
+ this->value());
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void Int64Value::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const Int64Value* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Int64Value>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void Int64Value::MergeFrom(const Int64Value& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from.value() != 0) {
+ set_value(from.value());
+ }
+}
+
+void Int64Value::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void Int64Value::CopyFrom(const Int64Value& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Int64Value::IsInitialized() const {
+
+ return true;
+}
+
+void Int64Value::Swap(Int64Value* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void Int64Value::InternalSwap(Int64Value* other) {
+ std::swap(value_, other->value_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Int64Value::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = Int64Value_descriptor_;
+ metadata.reflection = Int64Value_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Int64Value
+
+// optional int64 value = 1;
+void Int64Value::clear_value() {
+ value_ = GOOGLE_LONGLONG(0);
+}
+ ::google::protobuf::int64 Int64Value::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Int64Value.value)
+ return value_;
+}
+ void Int64Value::set_value(::google::protobuf::int64 value) {
+
+ value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Int64Value.value)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int UInt64Value::kValueFieldNumber;
+#endif // !_MSC_VER
+
+UInt64Value::UInt64Value()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.UInt64Value)
+}
+
+void UInt64Value::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+UInt64Value::UInt64Value(const UInt64Value& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.UInt64Value)
+}
+
+void UInt64Value::SharedCtor() {
+ _is_default_instance_ = false;
+ _cached_size_ = 0;
+ value_ = GOOGLE_ULONGLONG(0);
+}
+
+UInt64Value::~UInt64Value() {
+ // @@protoc_insertion_point(destructor:google.protobuf.UInt64Value)
+ SharedDtor();
+}
+
+void UInt64Value::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void UInt64Value::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* UInt64Value::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return UInt64Value_descriptor_;
+}
+
+const UInt64Value& UInt64Value::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ return *default_instance_;
+}
+
+UInt64Value* UInt64Value::default_instance_ = NULL;
+
+UInt64Value* UInt64Value::New(::google::protobuf::Arena* arena) const {
+ UInt64Value* n = new UInt64Value;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void UInt64Value::Clear() {
+ value_ = GOOGLE_ULONGLONG(0);
+}
+
+bool UInt64Value::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.UInt64Value)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional uint64 value = 1;
+ case 1: {
+ if (tag == 8) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
+ input, &value_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.UInt64Value)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.UInt64Value)
+ return false;
+#undef DO_
+}
+
+void UInt64Value::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.UInt64Value)
+ // optional uint64 value = 1;
+ if (this->value() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteUInt64(1, this->value(), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.UInt64Value)
+}
+
+::google::protobuf::uint8* UInt64Value::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UInt64Value)
+ // optional uint64 value = 1;
+ if (this->value() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(1, this->value(), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UInt64Value)
+ return target;
+}
+
+int UInt64Value::ByteSize() const {
+ int total_size = 0;
+
+ // optional uint64 value = 1;
+ if (this->value() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::UInt64Size(
+ this->value());
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void UInt64Value::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const UInt64Value* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const UInt64Value>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void UInt64Value::MergeFrom(const UInt64Value& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from.value() != 0) {
+ set_value(from.value());
+ }
+}
+
+void UInt64Value::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void UInt64Value::CopyFrom(const UInt64Value& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool UInt64Value::IsInitialized() const {
+
+ return true;
+}
+
+void UInt64Value::Swap(UInt64Value* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void UInt64Value::InternalSwap(UInt64Value* other) {
+ std::swap(value_, other->value_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata UInt64Value::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = UInt64Value_descriptor_;
+ metadata.reflection = UInt64Value_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// UInt64Value
+
+// optional uint64 value = 1;
+void UInt64Value::clear_value() {
+ value_ = GOOGLE_ULONGLONG(0);
+}
+ ::google::protobuf::uint64 UInt64Value::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UInt64Value.value)
+ return value_;
+}
+ void UInt64Value::set_value(::google::protobuf::uint64 value) {
+
+ value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.UInt64Value.value)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int Int32Value::kValueFieldNumber;
+#endif // !_MSC_VER
+
+Int32Value::Int32Value()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.Int32Value)
+}
+
+void Int32Value::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+Int32Value::Int32Value(const Int32Value& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.Int32Value)
+}
+
+void Int32Value::SharedCtor() {
+ _is_default_instance_ = false;
+ _cached_size_ = 0;
+ value_ = 0;
+}
+
+Int32Value::~Int32Value() {
+ // @@protoc_insertion_point(destructor:google.protobuf.Int32Value)
+ SharedDtor();
+}
+
+void Int32Value::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void Int32Value::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Int32Value::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return Int32Value_descriptor_;
+}
+
+const Int32Value& Int32Value::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ return *default_instance_;
+}
+
+Int32Value* Int32Value::default_instance_ = NULL;
+
+Int32Value* Int32Value::New(::google::protobuf::Arena* arena) const {
+ Int32Value* n = new Int32Value;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void Int32Value::Clear() {
+ value_ = 0;
+}
+
+bool Int32Value::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.Int32Value)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional int32 value = 1;
+ case 1: {
+ if (tag == 8) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &value_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.Int32Value)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.Int32Value)
+ return false;
+#undef DO_
+}
+
+void Int32Value::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.Int32Value)
+ // optional int32 value = 1;
+ if (this->value() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->value(), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.Int32Value)
+}
+
+::google::protobuf::uint8* Int32Value::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Int32Value)
+ // optional int32 value = 1;
+ if (this->value() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->value(), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Int32Value)
+ return target;
+}
+
+int Int32Value::ByteSize() const {
+ int total_size = 0;
+
+ // optional int32 value = 1;
+ if (this->value() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->value());
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void Int32Value::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const Int32Value* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Int32Value>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void Int32Value::MergeFrom(const Int32Value& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from.value() != 0) {
+ set_value(from.value());
+ }
+}
+
+void Int32Value::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void Int32Value::CopyFrom(const Int32Value& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Int32Value::IsInitialized() const {
+
+ return true;
+}
+
+void Int32Value::Swap(Int32Value* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void Int32Value::InternalSwap(Int32Value* other) {
+ std::swap(value_, other->value_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Int32Value::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = Int32Value_descriptor_;
+ metadata.reflection = Int32Value_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Int32Value
+
+// optional int32 value = 1;
+void Int32Value::clear_value() {
+ value_ = 0;
+}
+ ::google::protobuf::int32 Int32Value::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Int32Value.value)
+ return value_;
+}
+ void Int32Value::set_value(::google::protobuf::int32 value) {
+
+ value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Int32Value.value)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int UInt32Value::kValueFieldNumber;
+#endif // !_MSC_VER
+
+UInt32Value::UInt32Value()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.UInt32Value)
+}
+
+void UInt32Value::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+UInt32Value::UInt32Value(const UInt32Value& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.UInt32Value)
+}
+
+void UInt32Value::SharedCtor() {
+ _is_default_instance_ = false;
+ _cached_size_ = 0;
+ value_ = 0u;
+}
+
+UInt32Value::~UInt32Value() {
+ // @@protoc_insertion_point(destructor:google.protobuf.UInt32Value)
+ SharedDtor();
+}
+
+void UInt32Value::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void UInt32Value::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* UInt32Value::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return UInt32Value_descriptor_;
+}
+
+const UInt32Value& UInt32Value::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ return *default_instance_;
+}
+
+UInt32Value* UInt32Value::default_instance_ = NULL;
+
+UInt32Value* UInt32Value::New(::google::protobuf::Arena* arena) const {
+ UInt32Value* n = new UInt32Value;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void UInt32Value::Clear() {
+ value_ = 0u;
+}
+
+bool UInt32Value::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.UInt32Value)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional uint32 value = 1;
+ case 1: {
+ if (tag == 8) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+ input, &value_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.UInt32Value)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.UInt32Value)
+ return false;
+#undef DO_
+}
+
+void UInt32Value::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.UInt32Value)
+ // optional uint32 value = 1;
+ if (this->value() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->value(), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.UInt32Value)
+}
+
+::google::protobuf::uint8* UInt32Value::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UInt32Value)
+ // optional uint32 value = 1;
+ if (this->value() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(1, this->value(), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UInt32Value)
+ return target;
+}
+
+int UInt32Value::ByteSize() const {
+ int total_size = 0;
+
+ // optional uint32 value = 1;
+ if (this->value() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::UInt32Size(
+ this->value());
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void UInt32Value::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const UInt32Value* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const UInt32Value>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void UInt32Value::MergeFrom(const UInt32Value& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from.value() != 0) {
+ set_value(from.value());
+ }
+}
+
+void UInt32Value::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void UInt32Value::CopyFrom(const UInt32Value& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool UInt32Value::IsInitialized() const {
+
+ return true;
+}
+
+void UInt32Value::Swap(UInt32Value* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void UInt32Value::InternalSwap(UInt32Value* other) {
+ std::swap(value_, other->value_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata UInt32Value::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = UInt32Value_descriptor_;
+ metadata.reflection = UInt32Value_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// UInt32Value
+
+// optional uint32 value = 1;
+void UInt32Value::clear_value() {
+ value_ = 0u;
+}
+ ::google::protobuf::uint32 UInt32Value::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UInt32Value.value)
+ return value_;
+}
+ void UInt32Value::set_value(::google::protobuf::uint32 value) {
+
+ value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.UInt32Value.value)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int BoolValue::kValueFieldNumber;
+#endif // !_MSC_VER
+
+BoolValue::BoolValue()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.BoolValue)
+}
+
+void BoolValue::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+BoolValue::BoolValue(const BoolValue& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.BoolValue)
+}
+
+void BoolValue::SharedCtor() {
+ _is_default_instance_ = false;
+ _cached_size_ = 0;
+ value_ = false;
+}
+
+BoolValue::~BoolValue() {
+ // @@protoc_insertion_point(destructor:google.protobuf.BoolValue)
+ SharedDtor();
+}
+
+void BoolValue::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void BoolValue::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* BoolValue::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return BoolValue_descriptor_;
+}
+
+const BoolValue& BoolValue::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ return *default_instance_;
+}
+
+BoolValue* BoolValue::default_instance_ = NULL;
+
+BoolValue* BoolValue::New(::google::protobuf::Arena* arena) const {
+ BoolValue* n = new BoolValue;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void BoolValue::Clear() {
+ value_ = false;
+}
+
+bool BoolValue::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.BoolValue)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional bool value = 1;
+ case 1: {
+ if (tag == 8) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &value_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.BoolValue)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.BoolValue)
+ return false;
+#undef DO_
+}
+
+void BoolValue::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.BoolValue)
+ // optional bool value = 1;
+ if (this->value() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->value(), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.BoolValue)
+}
+
+::google::protobuf::uint8* BoolValue::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.BoolValue)
+ // optional bool value = 1;
+ if (this->value() != 0) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->value(), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.BoolValue)
+ return target;
+}
+
+int BoolValue::ByteSize() const {
+ int total_size = 0;
+
+ // optional bool value = 1;
+ if (this->value() != 0) {
+ total_size += 1 + 1;
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void BoolValue::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const BoolValue* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const BoolValue>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void BoolValue::MergeFrom(const BoolValue& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from.value() != 0) {
+ set_value(from.value());
+ }
+}
+
+void BoolValue::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void BoolValue::CopyFrom(const BoolValue& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool BoolValue::IsInitialized() const {
+
+ return true;
+}
+
+void BoolValue::Swap(BoolValue* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void BoolValue::InternalSwap(BoolValue* other) {
+ std::swap(value_, other->value_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata BoolValue::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = BoolValue_descriptor_;
+ metadata.reflection = BoolValue_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// BoolValue
+
+// optional bool value = 1;
+void BoolValue::clear_value() {
+ value_ = false;
+}
+ bool BoolValue::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.BoolValue.value)
+ return value_;
+}
+ void BoolValue::set_value(bool value) {
+
+ value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.BoolValue.value)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int StringValue::kValueFieldNumber;
+#endif // !_MSC_VER
+
+StringValue::StringValue()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.StringValue)
+}
+
+void StringValue::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+StringValue::StringValue(const StringValue& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.StringValue)
+}
+
+void StringValue::SharedCtor() {
+ _is_default_instance_ = false;
+ ::google::protobuf::internal::GetEmptyString();
+ _cached_size_ = 0;
+ value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+StringValue::~StringValue() {
+ // @@protoc_insertion_point(destructor:google.protobuf.StringValue)
+ SharedDtor();
+}
+
+void StringValue::SharedDtor() {
+ value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (this != default_instance_) {
+ }
+}
+
+void StringValue::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* StringValue::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return StringValue_descriptor_;
+}
+
+const StringValue& StringValue::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ return *default_instance_;
+}
+
+StringValue* StringValue::default_instance_ = NULL;
+
+StringValue* StringValue::New(::google::protobuf::Arena* arena) const {
+ StringValue* n = new StringValue;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void StringValue::Clear() {
+ value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+bool StringValue::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.StringValue)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional string value = 1;
+ case 1: {
+ if (tag == 10) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_value()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->value().data(), this->value().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.StringValue.value");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.StringValue)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.StringValue)
+ return false;
+#undef DO_
+}
+
+void StringValue::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.StringValue)
+ // optional string value = 1;
+ if (this->value().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->value().data(), this->value().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.StringValue.value");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 1, this->value(), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.StringValue)
+}
+
+::google::protobuf::uint8* StringValue::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.StringValue)
+ // optional string value = 1;
+ if (this->value().size() > 0) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->value().data(), this->value().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.StringValue.value");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 1, this->value(), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.StringValue)
+ return target;
+}
+
+int StringValue::ByteSize() const {
+ int total_size = 0;
+
+ // optional string value = 1;
+ if (this->value().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->value());
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void StringValue::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const StringValue* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const StringValue>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void StringValue::MergeFrom(const StringValue& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from.value().size() > 0) {
+
+ value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_);
+ }
+}
+
+void StringValue::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void StringValue::CopyFrom(const StringValue& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool StringValue::IsInitialized() const {
+
+ return true;
+}
+
+void StringValue::Swap(StringValue* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void StringValue::InternalSwap(StringValue* other) {
+ value_.Swap(&other->value_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata StringValue::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = StringValue_descriptor_;
+ metadata.reflection = StringValue_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// StringValue
+
+// optional string value = 1;
+void StringValue::clear_value() {
+ value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& StringValue::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.StringValue.value)
+ return value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void StringValue::set_value(const ::std::string& value) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.StringValue.value)
+}
+ void StringValue::set_value(const char* value) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.StringValue.value)
+}
+ void StringValue::set_value(const char* value, size_t size) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.StringValue.value)
+}
+ ::std::string* StringValue::mutable_value() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.StringValue.value)
+ return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* StringValue::release_value() {
+
+ return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void StringValue::set_allocated_value(::std::string* value) {
+ if (value != NULL) {
+
+ } else {
+
+ }
+ value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.StringValue.value)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int BytesValue::kValueFieldNumber;
+#endif // !_MSC_VER
+
+BytesValue::BytesValue()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.BytesValue)
+}
+
+void BytesValue::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+BytesValue::BytesValue(const BytesValue& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.BytesValue)
+}
+
+void BytesValue::SharedCtor() {
+ _is_default_instance_ = false;
+ ::google::protobuf::internal::GetEmptyString();
+ _cached_size_ = 0;
+ value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+BytesValue::~BytesValue() {
+ // @@protoc_insertion_point(destructor:google.protobuf.BytesValue)
+ SharedDtor();
+}
+
+void BytesValue::SharedDtor() {
+ value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ if (this != default_instance_) {
+ }
+}
+
+void BytesValue::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* BytesValue::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return BytesValue_descriptor_;
+}
+
+const BytesValue& BytesValue::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ return *default_instance_;
+}
+
+BytesValue* BytesValue::default_instance_ = NULL;
+
+BytesValue* BytesValue::New(::google::protobuf::Arena* arena) const {
+ BytesValue* n = new BytesValue;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void BytesValue::Clear() {
+ value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+bool BytesValue::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.BytesValue)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional bytes value = 1;
+ case 1: {
+ if (tag == 10) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+ input, this->mutable_value()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.BytesValue)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.BytesValue)
+ return false;
+#undef DO_
+}
+
+void BytesValue::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.BytesValue)
+ // optional bytes value = 1;
+ if (this->value().size() > 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
+ 1, this->value(), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:google.protobuf.BytesValue)
+}
+
+::google::protobuf::uint8* BytesValue::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.BytesValue)
+ // optional bytes value = 1;
+ if (this->value().size() > 0) {
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
+ 1, this->value(), target);
+ }
+
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.BytesValue)
+ return target;
+}
+
+int BytesValue::ByteSize() const {
+ int total_size = 0;
+
+ // optional bytes value = 1;
+ if (this->value().size() > 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::BytesSize(
+ this->value());
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void BytesValue::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const BytesValue* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const BytesValue>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void BytesValue::MergeFrom(const BytesValue& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from.value().size() > 0) {
+
+ value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_);
+ }
+}
+
+void BytesValue::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void BytesValue::CopyFrom(const BytesValue& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool BytesValue::IsInitialized() const {
+
+ return true;
+}
+
+void BytesValue::Swap(BytesValue* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void BytesValue::InternalSwap(BytesValue* other) {
+ value_.Swap(&other->value_);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata BytesValue::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = BytesValue_descriptor_;
+ metadata.reflection = BytesValue_reflection_;
+ return metadata;
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// BytesValue
+
+// optional bytes value = 1;
+void BytesValue::clear_value() {
+ value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ const ::std::string& BytesValue::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.BytesValue.value)
+ return value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void BytesValue::set_value(const ::std::string& value) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.BytesValue.value)
+}
+ void BytesValue::set_value(const char* value) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.BytesValue.value)
+}
+ void BytesValue::set_value(const void* value, size_t size) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.BytesValue.value)
+}
+ ::std::string* BytesValue::mutable_value() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.BytesValue.value)
+ return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* BytesValue::release_value() {
+
+ return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void BytesValue::set_allocated_value(::std::string* value) {
+ if (value != NULL) {
+
+ } else {
+
+ }
+ value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.BytesValue.value)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h
new file mode 100644
index 00000000..387ebd7c
--- /dev/null
+++ b/src/google/protobuf/wrappers.pb.h
@@ -0,0 +1,1011 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/wrappers.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fwrappers_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fwrappers_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+class DoubleValue;
+class FloatValue;
+class Int64Value;
+class UInt64Value;
+class Int32Value;
+class UInt32Value;
+class BoolValue;
+class StringValue;
+class BytesValue;
+
+// ===================================================================
+
+class LIBPROTOBUF_EXPORT DoubleValue : public ::google::protobuf::Message {
+ public:
+ DoubleValue();
+ virtual ~DoubleValue();
+
+ DoubleValue(const DoubleValue& from);
+
+ inline DoubleValue& operator=(const DoubleValue& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const DoubleValue& default_instance();
+
+ void Swap(DoubleValue* other);
+
+ // implements Message ----------------------------------------------
+
+ inline DoubleValue* New() const { return New(NULL); }
+
+ DoubleValue* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const DoubleValue& from);
+ void MergeFrom(const DoubleValue& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(DoubleValue* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional double value = 1;
+ void clear_value();
+ static const int kValueFieldNumber = 1;
+ double value() const;
+ void set_value(double value);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.DoubleValue)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ double value_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+ void InitAsDefaultInstance();
+ static DoubleValue* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT FloatValue : public ::google::protobuf::Message {
+ public:
+ FloatValue();
+ virtual ~FloatValue();
+
+ FloatValue(const FloatValue& from);
+
+ inline FloatValue& operator=(const FloatValue& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const FloatValue& default_instance();
+
+ void Swap(FloatValue* other);
+
+ // implements Message ----------------------------------------------
+
+ inline FloatValue* New() const { return New(NULL); }
+
+ FloatValue* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const FloatValue& from);
+ void MergeFrom(const FloatValue& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(FloatValue* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional float value = 1;
+ void clear_value();
+ static const int kValueFieldNumber = 1;
+ float value() const;
+ void set_value(float value);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.FloatValue)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ float value_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+ void InitAsDefaultInstance();
+ static FloatValue* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT Int64Value : public ::google::protobuf::Message {
+ public:
+ Int64Value();
+ virtual ~Int64Value();
+
+ Int64Value(const Int64Value& from);
+
+ inline Int64Value& operator=(const Int64Value& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const Int64Value& default_instance();
+
+ void Swap(Int64Value* other);
+
+ // implements Message ----------------------------------------------
+
+ inline Int64Value* New() const { return New(NULL); }
+
+ Int64Value* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const Int64Value& from);
+ void MergeFrom(const Int64Value& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(Int64Value* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional int64 value = 1;
+ void clear_value();
+ static const int kValueFieldNumber = 1;
+ ::google::protobuf::int64 value() const;
+ void set_value(::google::protobuf::int64 value);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.Int64Value)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::int64 value_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+ void InitAsDefaultInstance();
+ static Int64Value* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT UInt64Value : public ::google::protobuf::Message {
+ public:
+ UInt64Value();
+ virtual ~UInt64Value();
+
+ UInt64Value(const UInt64Value& from);
+
+ inline UInt64Value& operator=(const UInt64Value& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const UInt64Value& default_instance();
+
+ void Swap(UInt64Value* other);
+
+ // implements Message ----------------------------------------------
+
+ inline UInt64Value* New() const { return New(NULL); }
+
+ UInt64Value* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const UInt64Value& from);
+ void MergeFrom(const UInt64Value& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(UInt64Value* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional uint64 value = 1;
+ void clear_value();
+ static const int kValueFieldNumber = 1;
+ ::google::protobuf::uint64 value() const;
+ void set_value(::google::protobuf::uint64 value);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.UInt64Value)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::uint64 value_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+ void InitAsDefaultInstance();
+ static UInt64Value* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT Int32Value : public ::google::protobuf::Message {
+ public:
+ Int32Value();
+ virtual ~Int32Value();
+
+ Int32Value(const Int32Value& from);
+
+ inline Int32Value& operator=(const Int32Value& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const Int32Value& default_instance();
+
+ void Swap(Int32Value* other);
+
+ // implements Message ----------------------------------------------
+
+ inline Int32Value* New() const { return New(NULL); }
+
+ Int32Value* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const Int32Value& from);
+ void MergeFrom(const Int32Value& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(Int32Value* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional int32 value = 1;
+ void clear_value();
+ static const int kValueFieldNumber = 1;
+ ::google::protobuf::int32 value() const;
+ void set_value(::google::protobuf::int32 value);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.Int32Value)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::int32 value_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+ void InitAsDefaultInstance();
+ static Int32Value* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT UInt32Value : public ::google::protobuf::Message {
+ public:
+ UInt32Value();
+ virtual ~UInt32Value();
+
+ UInt32Value(const UInt32Value& from);
+
+ inline UInt32Value& operator=(const UInt32Value& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const UInt32Value& default_instance();
+
+ void Swap(UInt32Value* other);
+
+ // implements Message ----------------------------------------------
+
+ inline UInt32Value* New() const { return New(NULL); }
+
+ UInt32Value* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const UInt32Value& from);
+ void MergeFrom(const UInt32Value& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(UInt32Value* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional uint32 value = 1;
+ void clear_value();
+ static const int kValueFieldNumber = 1;
+ ::google::protobuf::uint32 value() const;
+ void set_value(::google::protobuf::uint32 value);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.UInt32Value)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::uint32 value_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+ void InitAsDefaultInstance();
+ static UInt32Value* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT BoolValue : public ::google::protobuf::Message {
+ public:
+ BoolValue();
+ virtual ~BoolValue();
+
+ BoolValue(const BoolValue& from);
+
+ inline BoolValue& operator=(const BoolValue& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const BoolValue& default_instance();
+
+ void Swap(BoolValue* other);
+
+ // implements Message ----------------------------------------------
+
+ inline BoolValue* New() const { return New(NULL); }
+
+ BoolValue* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const BoolValue& from);
+ void MergeFrom(const BoolValue& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(BoolValue* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional bool value = 1;
+ void clear_value();
+ static const int kValueFieldNumber = 1;
+ bool value() const;
+ void set_value(bool value);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.BoolValue)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ bool value_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+ void InitAsDefaultInstance();
+ static BoolValue* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT StringValue : public ::google::protobuf::Message {
+ public:
+ StringValue();
+ virtual ~StringValue();
+
+ StringValue(const StringValue& from);
+
+ inline StringValue& operator=(const StringValue& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const StringValue& default_instance();
+
+ void Swap(StringValue* other);
+
+ // implements Message ----------------------------------------------
+
+ inline StringValue* New() const { return New(NULL); }
+
+ StringValue* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const StringValue& from);
+ void MergeFrom(const StringValue& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(StringValue* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional string value = 1;
+ void clear_value();
+ static const int kValueFieldNumber = 1;
+ const ::std::string& value() const;
+ void set_value(const ::std::string& value);
+ void set_value(const char* value);
+ void set_value(const char* value, size_t size);
+ ::std::string* mutable_value();
+ ::std::string* release_value();
+ void set_allocated_value(::std::string* value);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.StringValue)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::internal::ArenaStringPtr value_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+ void InitAsDefaultInstance();
+ static StringValue* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT BytesValue : public ::google::protobuf::Message {
+ public:
+ BytesValue();
+ virtual ~BytesValue();
+
+ BytesValue(const BytesValue& from);
+
+ inline BytesValue& operator=(const BytesValue& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const BytesValue& default_instance();
+
+ void Swap(BytesValue* other);
+
+ // implements Message ----------------------------------------------
+
+ inline BytesValue* New() const { return New(NULL); }
+
+ BytesValue* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const BytesValue& from);
+ void MergeFrom(const BytesValue& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(BytesValue* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional bytes value = 1;
+ void clear_value();
+ static const int kValueFieldNumber = 1;
+ const ::std::string& value() const;
+ void set_value(const ::std::string& value);
+ void set_value(const char* value);
+ void set_value(const void* value, size_t size);
+ ::std::string* mutable_value();
+ ::std::string* release_value();
+ void set_allocated_value(::std::string* value);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.BytesValue)
+ private:
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ bool _is_default_instance_;
+ ::google::protobuf::internal::ArenaStringPtr value_;
+ mutable int _cached_size_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto();
+
+ void InitAsDefaultInstance();
+ static BytesValue* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// DoubleValue
+
+// optional double value = 1;
+inline void DoubleValue::clear_value() {
+ value_ = 0;
+}
+inline double DoubleValue::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DoubleValue.value)
+ return value_;
+}
+inline void DoubleValue::set_value(double value) {
+
+ value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.DoubleValue.value)
+}
+
+// -------------------------------------------------------------------
+
+// FloatValue
+
+// optional float value = 1;
+inline void FloatValue::clear_value() {
+ value_ = 0;
+}
+inline float FloatValue::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FloatValue.value)
+ return value_;
+}
+inline void FloatValue::set_value(float value) {
+
+ value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FloatValue.value)
+}
+
+// -------------------------------------------------------------------
+
+// Int64Value
+
+// optional int64 value = 1;
+inline void Int64Value::clear_value() {
+ value_ = GOOGLE_LONGLONG(0);
+}
+inline ::google::protobuf::int64 Int64Value::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Int64Value.value)
+ return value_;
+}
+inline void Int64Value::set_value(::google::protobuf::int64 value) {
+
+ value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Int64Value.value)
+}
+
+// -------------------------------------------------------------------
+
+// UInt64Value
+
+// optional uint64 value = 1;
+inline void UInt64Value::clear_value() {
+ value_ = GOOGLE_ULONGLONG(0);
+}
+inline ::google::protobuf::uint64 UInt64Value::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UInt64Value.value)
+ return value_;
+}
+inline void UInt64Value::set_value(::google::protobuf::uint64 value) {
+
+ value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.UInt64Value.value)
+}
+
+// -------------------------------------------------------------------
+
+// Int32Value
+
+// optional int32 value = 1;
+inline void Int32Value::clear_value() {
+ value_ = 0;
+}
+inline ::google::protobuf::int32 Int32Value::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.Int32Value.value)
+ return value_;
+}
+inline void Int32Value::set_value(::google::protobuf::int32 value) {
+
+ value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.Int32Value.value)
+}
+
+// -------------------------------------------------------------------
+
+// UInt32Value
+
+// optional uint32 value = 1;
+inline void UInt32Value::clear_value() {
+ value_ = 0u;
+}
+inline ::google::protobuf::uint32 UInt32Value::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UInt32Value.value)
+ return value_;
+}
+inline void UInt32Value::set_value(::google::protobuf::uint32 value) {
+
+ value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.UInt32Value.value)
+}
+
+// -------------------------------------------------------------------
+
+// BoolValue
+
+// optional bool value = 1;
+inline void BoolValue::clear_value() {
+ value_ = false;
+}
+inline bool BoolValue::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.BoolValue.value)
+ return value_;
+}
+inline void BoolValue::set_value(bool value) {
+
+ value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.BoolValue.value)
+}
+
+// -------------------------------------------------------------------
+
+// StringValue
+
+// optional string value = 1;
+inline void StringValue::clear_value() {
+ value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& StringValue::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.StringValue.value)
+ return value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void StringValue::set_value(const ::std::string& value) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.StringValue.value)
+}
+inline void StringValue::set_value(const char* value) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.StringValue.value)
+}
+inline void StringValue::set_value(const char* value, size_t size) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.StringValue.value)
+}
+inline ::std::string* StringValue::mutable_value() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.StringValue.value)
+ return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* StringValue::release_value() {
+
+ return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void StringValue::set_allocated_value(::std::string* value) {
+ if (value != NULL) {
+
+ } else {
+
+ }
+ value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.StringValue.value)
+}
+
+// -------------------------------------------------------------------
+
+// BytesValue
+
+// optional bytes value = 1;
+inline void BytesValue::clear_value() {
+ value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& BytesValue::value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.BytesValue.value)
+ return value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void BytesValue::set_value(const ::std::string& value) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.BytesValue.value)
+}
+inline void BytesValue::set_value(const char* value) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.BytesValue.value)
+}
+inline void BytesValue::set_value(const void* value, size_t size) {
+
+ value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.BytesValue.value)
+}
+inline ::std::string* BytesValue::mutable_value() {
+
+ // @@protoc_insertion_point(field_mutable:google.protobuf.BytesValue.value)
+ return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* BytesValue::release_value() {
+
+ return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void BytesValue::set_allocated_value(::std::string* value) {
+ if (value != NULL) {
+
+ } else {
+
+ }
+ value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.BytesValue.value)
+}
+
+#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#endif // PROTOBUF_google_2fprotobuf_2fwrappers_2eproto__INCLUDED
diff --git a/src/google/protobuf/wrappers.proto b/src/google/protobuf/wrappers.proto
new file mode 100644
index 00000000..6d3181bf
--- /dev/null
+++ b/src/google/protobuf/wrappers.proto
@@ -0,0 +1,99 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Wrappers for primitive (non-message) types. These types are useful
+// for embedding primitives in the `google.protobuf.Any` type and for places
+// where we need to distinguish between the absence of a primitive
+// typed field and its default value.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option java_multiple_files = true;
+option java_outer_classname = "WrappersProto";
+option java_package = "com.google.protobuf";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option objc_class_prefix = "GPB";
+
+
+// Wrapper message for double.
+message DoubleValue {
+ // The double value.
+ double value = 1;
+}
+
+// Wrapper message for float.
+message FloatValue {
+ // The float value.
+ float value = 1;
+}
+
+// Wrapper message for int64.
+message Int64Value {
+ // The int64 value.
+ int64 value = 1;
+}
+
+// Wrapper message for uint64.
+message UInt64Value {
+ // The uint64 value.
+ uint64 value = 1;
+}
+
+// Wrapper message for int32.
+message Int32Value {
+ // The int32 value.
+ int32 value = 1;
+}
+
+// Wrapper message for uint32.
+message UInt32Value {
+ // The uint32 value.
+ uint32 value = 1;
+}
+
+// Wrapper message for bool.
+message BoolValue {
+ // The bool value.
+ bool value = 1;
+}
+
+// Wrapper message for string.
+message StringValue {
+ // The string value.
+ string value = 1;
+}
+
+// Wrapper message for bytes.
+message BytesValue {
+ // The bytes value.
+ bytes value = 1;
+}