From eee38b0c018b3279f77d03dff796f440f40d3516 Mon Sep 17 00:00:00 2001 From: Feng Xiao Date: Sat, 22 Aug 2015 18:25:48 -0700 Subject: Down-integrate from google3. --- src/google/protobuf/any.cc | 4 +- src/google/protobuf/any.h | 2 +- src/google/protobuf/arena.cc | 40 +- src/google/protobuf/arena.h | 178 +++-- src/google/protobuf/arena_test_util.cc | 1 + src/google/protobuf/arena_unittest.cc | 55 +- src/google/protobuf/arenastring.h | 11 +- src/google/protobuf/arenastring_unittest.cc | 1 + src/google/protobuf/compiler/code_generator.cc | 1 + .../protobuf/compiler/command_line_interface.cc | 5 + .../compiler/command_line_interface_unittest.cc | 33 + .../compiler/cpp/cpp_bootstrap_unittest.cc | 3 +- src/google/protobuf/compiler/cpp/cpp_enum.cc | 8 +- src/google/protobuf/compiler/cpp/cpp_enum.h | 5 +- src/google/protobuf/compiler/cpp/cpp_enum_field.cc | 1 - src/google/protobuf/compiler/cpp/cpp_field.cc | 1 + src/google/protobuf/compiler/cpp/cpp_file.cc | 254 ++++++- src/google/protobuf/compiler/cpp/cpp_file.h | 32 +- src/google/protobuf/compiler/cpp/cpp_generator.cc | 13 +- src/google/protobuf/compiler/cpp/cpp_helpers.cc | 24 +- src/google/protobuf/compiler/cpp/cpp_helpers.h | 7 + src/google/protobuf/compiler/cpp/cpp_map_field.cc | 9 +- src/google/protobuf/compiler/cpp/cpp_map_field.h | 1 + src/google/protobuf/compiler/cpp/cpp_message.cc | 187 +++--- src/google/protobuf/compiler/cpp/cpp_message.h | 9 +- .../protobuf/compiler/cpp/cpp_message_field.cc | 616 +++++++++++++---- .../protobuf/compiler/cpp/cpp_message_field.h | 20 +- .../protobuf/compiler/cpp/cpp_string_field.cc | 31 +- .../protobuf/compiler/cpp/cpp_string_field.h | 1 + src/google/protobuf/compiler/cpp/cpp_unittest.cc | 2 + src/google/protobuf/compiler/importer_unittest.cc | 1 + src/google/protobuf/compiler/java/java_enum.cc | 4 +- .../protobuf/compiler/java/java_enum_field.cc | 1 + .../protobuf/compiler/java/java_enum_field_lite.cc | 1 + .../protobuf/compiler/java/java_enum_lite.cc | 226 +++++++ src/google/protobuf/compiler/java/java_enum_lite.h | 99 +++ src/google/protobuf/compiler/java/java_field.cc | 1 + src/google/protobuf/compiler/java/java_field.h | 1 + src/google/protobuf/compiler/java/java_helpers.h | 4 + .../protobuf/compiler/java/java_map_field.cc | 24 + .../protobuf/compiler/java/java_map_field_lite.cc | 24 + src/google/protobuf/compiler/java/java_message.cc | 132 +++- src/google/protobuf/compiler/java/java_message.h | 1 + .../protobuf/compiler/java/java_message_field.cc | 13 +- .../compiler/java/java_message_field_lite.cc | 14 +- .../protobuf/compiler/java/java_message_lite.cc | 92 +-- .../protobuf/compiler/java/java_primitive_field.cc | 1 + .../compiler/java/java_primitive_field_lite.cc | 1 + src/google/protobuf/compiler/java/java_service.cc | 1 - .../protobuf/compiler/java/java_string_field.cc | 22 +- .../compiler/java/java_string_field_lite.cc | 189 ++---- src/google/protobuf/compiler/parser.cc | 1 + src/google/protobuf/compiler/parser.h | 6 +- src/google/protobuf/compiler/plugin.cc | 1 + src/google/protobuf/compiler/plugin.pb.cc | 36 +- src/google/protobuf/compiler/plugin.pb.h | 28 +- .../protobuf/compiler/python/python_generator.cc | 1 + .../protobuf/compiler/python/python_generator.h | 1 + src/google/protobuf/compiler/subprocess.cc | 1 + src/google/protobuf/descriptor.cc | 24 +- src/google/protobuf/descriptor.h | 4 +- src/google/protobuf/descriptor.pb.cc | 482 +++++++------- src/google/protobuf/descriptor.pb.h | 346 +++++----- src/google/protobuf/descriptor.proto | 11 +- .../protobuf/descriptor_database_unittest.cc | 2 + src/google/protobuf/descriptor_unittest.cc | 85 ++- src/google/protobuf/dynamic_message.cc | 27 +- src/google/protobuf/dynamic_message.h | 1 + src/google/protobuf/dynamic_message_unittest.cc | 2 + src/google/protobuf/extension_set.h | 7 + src/google/protobuf/extension_set_heavy.cc | 16 +- src/google/protobuf/extension_set_unittest.cc | 3 +- .../protobuf/generated_message_reflection.cc | 133 +++- src/google/protobuf/generated_message_reflection.h | 40 +- .../generated_message_reflection_unittest.cc | 52 ++ src/google/protobuf/io/coded_stream.cc | 5 +- src/google/protobuf/io/coded_stream.h | 31 +- src/google/protobuf/io/coded_stream_inl.h | 1 + src/google/protobuf/io/coded_stream_unittest.cc | 2 + src/google/protobuf/io/gzip_stream.cc | 2 + src/google/protobuf/io/printer.cc | 1 + src/google/protobuf/io/printer_unittest.cc | 1 + src/google/protobuf/io/strtod.cc | 1 + src/google/protobuf/io/tokenizer.cc | 1 + src/google/protobuf/io/tokenizer.h | 1 + src/google/protobuf/io/tokenizer_unittest.cc | 1 + src/google/protobuf/io/zero_copy_stream.cc | 1 + src/google/protobuf/io/zero_copy_stream_impl.cc | 1 + .../protobuf/io/zero_copy_stream_impl_lite.cc | 1 + .../protobuf/io/zero_copy_stream_impl_lite.h | 1 + .../protobuf/io/zero_copy_stream_unittest.cc | 3 + src/google/protobuf/lite_unittest.cc | 39 +- src/google/protobuf/map.h | 423 +++++++++++- src/google/protobuf/map_entry.h | 81 ++- src/google/protobuf/map_entry_lite.h | 162 +++-- src/google/protobuf/map_field.cc | 316 +++++++++ src/google/protobuf/map_field.h | 194 +++++- src/google/protobuf/map_field_inl.h | 231 ++++++- src/google/protobuf/map_field_test.cc | 23 + src/google/protobuf/map_lite_unittest.proto | 17 +- src/google/protobuf/map_proto2_unittest.proto | 8 - src/google/protobuf/map_test.cc | 190 +++++- src/google/protobuf/map_test_util.cc | 726 +++++++++++++++++--- src/google/protobuf/map_test_util.h | 131 ++-- src/google/protobuf/map_test_util_impl.h | 16 + src/google/protobuf/map_type_handler.h | 729 +++++++++++++-------- src/google/protobuf/map_unittest.proto | 14 +- src/google/protobuf/message.cc | 19 + src/google/protobuf/message.h | 113 +++- src/google/protobuf/message_lite.cc | 62 +- src/google/protobuf/message_unittest.cc | 1 + src/google/protobuf/metadata.h | 17 +- src/google/protobuf/no_field_presence_test.cc | 40 ++ src/google/protobuf/proto3_arena_unittest.cc | 26 +- src/google/protobuf/proto_cast.h | 1 + src/google/protobuf/proto_cast_test.cc | 2 +- src/google/protobuf/reflection.h | 2 +- src/google/protobuf/reflection_ops_unittest.cc | 1 + src/google/protobuf/repeated_field.cc | 9 +- src/google/protobuf/repeated_field.h | 90 +-- src/google/protobuf/repeated_field_unittest.cc | 2 +- src/google/protobuf/service.h | 5 +- src/google/protobuf/test_util.cc | 1 + src/google/protobuf/test_util_lite.cc | 1 + src/google/protobuf/text_format_unittest.cc | 2 + src/google/protobuf/unittest_mset.proto | 19 +- src/google/protobuf/unknown_enum_impl.h | 9 +- src/google/protobuf/unknown_enum_test.proto | 2 + src/google/protobuf/unknown_field_set.cc | 1 + src/google/protobuf/unknown_field_set.h | 1 + src/google/protobuf/unknown_field_set_unittest.cc | 3 + src/google/protobuf/util/internal/datapiece.cc | 6 +- .../util/internal/default_value_objectwriter.cc | 66 +- .../util/internal/default_value_objectwriter.h | 13 +- .../internal/default_value_objectwriter_test.cc | 58 +- src/google/protobuf/util/internal/error_listener.h | 2 + .../protobuf/util/internal/field_mask_utility.cc | 23 +- src/google/protobuf/util/internal/json_escaping.cc | 1 + .../protobuf/util/internal/json_objectwriter.cc | 3 +- .../util/internal/json_objectwriter_test.cc | 189 +++--- .../protobuf/util/internal/json_stream_parser.cc | 62 +- .../protobuf/util/internal/json_stream_parser.h | 12 +- .../util/internal/json_stream_parser_test.cc | 23 +- .../util/internal/protostream_objectsource.cc | 17 +- .../util/internal/protostream_objectsource.h | 10 +- .../util/internal/protostream_objectsource_test.cc | 40 +- .../util/internal/protostream_objectwriter.cc | 79 ++- .../util/internal/protostream_objectwriter.h | 41 +- .../util/internal/protostream_objectwriter_test.cc | 306 +++++++-- .../util/internal/snake2camel_objectwriter.h | 46 +- .../util/internal/snake2camel_objectwriter_test.cc | 260 +------- .../util/internal/testdata/default_value.proto | 7 + src/google/protobuf/util/internal/type_info.cc | 25 +- src/google/protobuf/util/internal/type_info.h | 15 +- .../util/internal/type_info_test_helper.cc | 7 +- src/google/protobuf/util/internal/utility.cc | 4 +- src/google/protobuf/util/internal/utility.h | 11 +- src/google/protobuf/util/json_util.h | 10 +- src/google/protobuf/util/json_util_test.cc | 43 +- src/google/protobuf/util/message_differencer.cc | 1 + .../protobuf/util/message_differencer_unittest.cc | 3 +- src/google/protobuf/util/type_resolver_util.cc | 43 ++ src/google/protobuf/util/type_resolver_util.h | 2 +- src/google/protobuf/wire_format.cc | 1 + src/google/protobuf/wire_format_lite.cc | 7 +- src/google/protobuf/wire_format_lite.h | 167 +++-- src/google/protobuf/wire_format_lite_inl.h | 1 + src/google/protobuf/wire_format_unittest.cc | 16 +- 168 files changed, 6502 insertions(+), 2618 deletions(-) (limited to 'src/google/protobuf') diff --git a/src/google/protobuf/any.cc b/src/google/protobuf/any.cc index c66fdfad..c6ed37ae 100644 --- a/src/google/protobuf/any.cc +++ b/src/google/protobuf/any.cc @@ -50,7 +50,7 @@ AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value) void AnyMetadata::PackFrom(const Message& message) { type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(), - GetTypeUrl(message.GetDescriptor())); + GetTypeUrl(message.GetDescriptor())); message.SerializeToString(value_->MutableNoArena( &::google::protobuf::internal::GetEmptyStringAlreadyInited())); } @@ -76,7 +76,7 @@ bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) { type_url.size() - prefix_len); return true; } - return true; + return false; } diff --git a/src/google/protobuf/any.h b/src/google/protobuf/any.h index f681eceb..7eeb6b70 100644 --- a/src/google/protobuf/any.h +++ b/src/google/protobuf/any.h @@ -34,9 +34,9 @@ #include #include -#include #include #include +#include namespace google { namespace protobuf { diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc index ed1c5ef2..907a6a20 100755 --- a/src/google/protobuf/arena.cc +++ b/src/google/protobuf/arena.cc @@ -66,8 +66,12 @@ void Arena::Init() { first_block->size = options_.initial_block_size; first_block->pos = kHeaderSize; first_block->next = NULL; - first_block->owner = &first_block->owner; - AddBlock(first_block); + // Thread which calls Init() owns the first block. This allows the + // single-threaded case to allocate on the first block without taking any + // locks. + first_block->owner = &thread_cache(); + SetThreadCacheBlock(first_block); + AddBlockInternal(first_block); owns_first_block_ = false; } @@ -80,7 +84,7 @@ void Arena::Init() { } Arena::~Arena() { - uint64 space_allocated = Reset(); + uint64 space_allocated = ResetInternal(); // Call the destruction hook if (options_.on_arena_destruction != NULL) { @@ -89,10 +93,14 @@ Arena::~Arena() { } uint64 Arena::Reset() { - CleanupList(); - uint64 space_allocated = FreeBlocks(); // Invalidate any ThreadCaches pointing to any blocks we just destroyed. lifecycle_id_ = lifecycle_id_generator_.GetNext(); + return ResetInternal(); +} + +uint64 Arena::ResetInternal() { + CleanupList(); + uint64 space_allocated = FreeBlocks(); // Call the reset hook if (options_.on_arena_reset != NULL) { @@ -137,6 +145,10 @@ Arena::Block* Arena::NewBlock(void* me, Block* my_last_block, size_t n, void Arena::AddBlock(Block* b) { MutexLock l(&blocks_lock_); + AddBlockInternal(b); +} + +void Arena::AddBlockInternal(Block* b) { b->next = reinterpret_cast(google::protobuf::internal::NoBarrier_Load(&blocks_)); google::protobuf::internal::Release_Store(&blocks_, reinterpret_cast(b)); if (b->avail() != 0) { @@ -181,16 +193,6 @@ void* Arena::AllocateAligned(const std::type_info* allocated, size_t n) { void* me = &thread_cache(); Block* b = reinterpret_cast(google::protobuf::internal::Acquire_Load(&hint_)); if (!b || b->owner != me || b->avail() < n) { - // If the next block to allocate from is the first block, try to claim it - // for this thread. - if (!owns_first_block_ && b->next == NULL) { - MutexLock l(&blocks_lock_); - if (b->owner == &b->owner && b->avail() >= n) { - b->owner = me; - SetThreadCacheBlock(b); - return AllocFromBlock(b, n); - } - } return SlowAlloc(n); } return AllocFromBlock(b, n); @@ -267,8 +269,12 @@ uint64 Arena::FreeBlocks() { // Make the first block that was passed in through ArenaOptions // available for reuse. first_block->pos = kHeaderSize; - first_block->owner = &first_block->owner; - AddBlock(first_block); + // Thread which calls Reset() owns the first block. This allows the + // single-threaded case to allocate on the first block without taking any + // locks. + first_block->owner = &thread_cache(); + SetThreadCacheBlock(first_block); + AddBlockInternal(first_block); } return space_allocated; } diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index 51149bae..f06be4a3 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -31,6 +31,7 @@ #ifndef GOOGLE_PROTOBUF_ARENA_H__ #define GOOGLE_PROTOBUF_ARENA_H__ +#include #if __cplusplus >= 201103L #include #endif @@ -39,7 +40,8 @@ #include #include #include -#include +#include +#include #include namespace google { @@ -414,6 +416,9 @@ class LIBPROTOBUF_EXPORT Arena { // trivially destructible. template GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* CreateArray(::google::protobuf::Arena* arena, size_t num_elements) { + GOOGLE_CHECK_LE(num_elements, + std::numeric_limits::max() / sizeof(T)) + << "Requested size is too large to fit into size_t."; if (arena == NULL) { return static_cast(::operator new[](num_elements * sizeof(T))); } else { @@ -425,16 +430,16 @@ 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; + GOOGLE_ATTRIBUTE_NOINLINE uint64 SpaceAllocated() const; // As above, but does not include any free space in underlying blocks. - uint64 SpaceUsed() const GOOGLE_ATTRIBUTE_NOINLINE; + GOOGLE_ATTRIBUTE_NOINLINE uint64 SpaceUsed() const; // Frees all storage allocated by this arena after calling destructors // registered with OwnDestructor() and freeing objects registered with Own(). // Any objects allocated on this arena are unusable after this call. It also // returns the total space used by the arena which is the sums of the sizes // of the allocated blocks. This method is not thread-safe. - uint64 Reset() GOOGLE_ATTRIBUTE_NOINLINE; + GOOGLE_ATTRIBUTE_NOINLINE uint64 Reset(); // Adds |object| to a list of heap-allocated objects to be freed with |delete| // when the arena is destroyed or reset. @@ -459,8 +464,8 @@ class LIBPROTOBUF_EXPORT Arena { // will be manually called when the arena is destroyed or reset. This differs // from OwnDestructor() in that any member function may be specified, not only // the class destructor. - void OwnCustomDestructor(void* object, void (*destruct)(void*)) - GOOGLE_ATTRIBUTE_NOINLINE { + GOOGLE_ATTRIBUTE_NOINLINE void OwnCustomDestructor(void* object, + void (*destruct)(void*)) { AddListNode(object, destruct); } @@ -469,7 +474,7 @@ class LIBPROTOBUF_EXPORT Arena { // latter is a virtual call, while this method is a templated call that // resolves at compile-time. template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static inline ::google::protobuf::Arena* GetArena(const T* value) { + static ::google::protobuf::Arena* GetArena(const T* value) { return GetArenaInternal(value, static_cast(0)); } @@ -507,7 +512,7 @@ class LIBPROTOBUF_EXPORT Arena { // aligned at a multiple of 8 bytes. size_t pos; size_t size; // total size of the block. - size_t avail() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE { return size - pos; } + GOOGLE_ATTRIBUTE_ALWAYS_INLINE size_t avail() const { return size - pos; } // data follows }; @@ -555,6 +560,33 @@ class LIBPROTOBUF_EXPORT Arena { return google::protobuf::internal::has_trivial_destructor::value; } + // Helper typetrait that indicates whether the desctructor of type T should be + // called when arena is destroyed at compile time. This is only to allow + // construction of higher-level templated utilities. + // is_destructor_skippable::value is an instance of google::protobuf::internal::true_type if the + // destructor of the message type T should not be called when arena is + // destroyed or google::protobuf::internal::has_trivial_destructor::value == true, and + // google::protobuf::internal::false_type otherwise. + // + // This is inside Arena because only Arena has the friend relationships + // necessary to see the underlying generated code traits. + template + struct is_destructor_skippable { + template + static char DestructorSkippable( + const typename U::DestructorSkippable_*); + template + static double DestructorSkippable(...); + + // This will resolve to either google::protobuf::internal::true_type or google::protobuf::internal::false_type. + typedef google::protobuf::internal::integral_constant(static_cast(0))) == + sizeof(char) || google::protobuf::internal::has_trivial_destructor::value == true> + type; + static const type value; + }; + + // CreateMessage requires that T supports arenas, but this private method // works whether or not T supports arenas. These are not exposed to user code // as it can cause confusing API usages, and end up having double free in @@ -574,14 +606,16 @@ class LIBPROTOBUF_EXPORT Arena { // Just allocate the required size for the given type assuming the // type has a trivial constructor. template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - inline T* CreateInternalRawArray(size_t num_elements) { + T* CreateInternalRawArray(size_t num_elements) { + GOOGLE_CHECK_LE(num_elements, + std::numeric_limits::max() / sizeof(T)) + << "Requested size is too large to fit into size_t."; return static_cast( AllocateAligned(RTTI_TYPE_ID(T), sizeof(T) * num_elements)); } template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - inline T* CreateInternal( - bool skip_explicit_ownership) { + T* CreateInternal(bool skip_explicit_ownership) { T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(); if (!skip_explicit_ownership) { AddListNode(t, &internal::arena_destruct_object); @@ -590,8 +624,7 @@ class LIBPROTOBUF_EXPORT Arena { } template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - inline T* CreateInternal( - bool skip_explicit_ownership, const Arg& arg) { + T* CreateInternal(bool skip_explicit_ownership, const Arg& arg) { T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg); if (!skip_explicit_ownership) { AddListNode(t, &internal::arena_destruct_object); @@ -600,7 +633,7 @@ class LIBPROTOBUF_EXPORT Arena { } template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - inline T* CreateInternal( + T* CreateInternal( bool skip_explicit_ownership, const Arg1& arg1, const Arg2& arg2) { T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2); if (!skip_explicit_ownership) { @@ -610,10 +643,10 @@ class LIBPROTOBUF_EXPORT Arena { } template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership, - const Arg1& arg1, - const Arg2& arg2, - const Arg3& arg3) { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership, + const Arg1& arg1, + const Arg2& arg2, + const Arg3& arg3) { T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2, arg3); if (!skip_explicit_ownership) { @@ -624,11 +657,11 @@ class LIBPROTOBUF_EXPORT Arena { template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership, - const Arg1& arg1, - const Arg2& arg2, - const Arg3& arg3, - const Arg4& arg4) { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership, + const Arg1& arg1, + const Arg2& arg2, + const Arg3& arg3, + const Arg4& arg4) { T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2, arg3, arg4); if (!skip_explicit_ownership) { @@ -639,12 +672,12 @@ class LIBPROTOBUF_EXPORT Arena { template - 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) { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership, + const Arg1& arg1, + const Arg2& arg2, + const Arg3& arg3, + const Arg4& arg4, + const Arg5& arg5) { T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2, arg3, arg4, arg5); if (!skip_explicit_ownership) { @@ -655,13 +688,13 @@ class LIBPROTOBUF_EXPORT Arena { template - 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) { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership, + const Arg1& arg1, + const Arg2& arg2, + const Arg3& arg3, + const Arg4& arg4, + const Arg5& arg5, + const Arg6& arg6) { T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2, arg3, arg4, arg5, arg6); if (!skip_explicit_ownership) { @@ -672,14 +705,14 @@ class LIBPROTOBUF_EXPORT Arena { template - 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) { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership, + const Arg1& arg1, + const Arg2& arg2, + const Arg3& arg3, + const Arg4& arg4, + const Arg5& arg5, + const Arg6& arg6, + const Arg7& arg7) { T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2, arg3, arg4, arg5, arg6, arg7); if (!skip_explicit_ownership) { @@ -691,15 +724,15 @@ class LIBPROTOBUF_EXPORT Arena { template - 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) { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership, + const Arg1& arg1, + const Arg2& arg2, + const Arg3& arg3, + const Arg4& arg4, + const Arg5& arg5, + const Arg6& arg6, + const Arg7& arg7, + const Arg8& arg8) { T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); if (!skip_explicit_ownership) { @@ -709,21 +742,21 @@ class LIBPROTOBUF_EXPORT Arena { } template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*) { + T* CreateMessageInternal(typename T::InternalArenaConstructable_*) { return CreateInternal(SkipDeleteList(static_cast(0)), this); } template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*, - const Arg& arg) { + T* CreateMessageInternal(typename T::InternalArenaConstructable_*, + const Arg& arg) { return CreateInternal(SkipDeleteList(static_cast(0)), this, arg); } template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*, - const Arg1& arg1, const Arg2& arg2) { + T* CreateMessageInternal(typename T::InternalArenaConstructable_*, + const Arg1& arg1, const Arg2& arg2) { return CreateInternal(SkipDeleteList(static_cast(0)), this, arg1, arg2); } @@ -734,19 +767,29 @@ class LIBPROTOBUF_EXPORT Arena { template static void CreateInArenaStorage(T* ptr, Arena* arena) { CreateInArenaStorageInternal(ptr, arena, is_arena_constructable::value); + RegisterDestructorInternal(ptr, arena, is_destructor_skippable::value); } + template static void CreateInArenaStorageInternal( T* ptr, Arena* arena, google::protobuf::internal::true_type) { new (ptr) T(arena); } - template static void CreateInArenaStorageInternal( T* ptr, Arena* arena, google::protobuf::internal::false_type) { new (ptr) T; } + template + static void RegisterDestructorInternal( + T* ptr, Arena* arena, google::protobuf::internal::true_type) {} + template + static void RegisterDestructorInternal( + T* ptr, Arena* arena, google::protobuf::internal::false_type) { + arena->OwnDestructor(ptr); + } + // These implement Own(), which registers an object for deletion (destructor // call and operator delete()). The second parameter has type 'true_type' if T // is a subtype of ::google::protobuf::Message and 'false_type' otherwise. Collapsing @@ -769,13 +812,13 @@ class LIBPROTOBUF_EXPORT Arena { // InternalArenaConstructable_ tags can be associated with an arena, and such // objects must implement a GetArenaNoVirtual() method. template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static inline ::google::protobuf::Arena* GetArenaInternal(const T* value, - typename T::InternalArenaConstructable_*) { + static ::google::protobuf::Arena* GetArenaInternal( + const T* value, typename T::InternalArenaConstructable_*) { return value->GetArenaNoVirtual(); } template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static inline ::google::protobuf::Arena* GetArenaInternal(const T* value, ...) { + static ::google::protobuf::Arena* GetArenaInternal(const T* value, ...) { return NULL; } @@ -785,7 +828,7 @@ class LIBPROTOBUF_EXPORT Arena { void* AllocateAligned(const std::type_info* allocated, size_t n); // Allocate an internal allocation, avoiding optional typed monitoring. - GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline void* AllocateAligned(size_t n) { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* AllocateAligned(size_t n) { return AllocateAligned(NULL, n); } @@ -803,6 +846,7 @@ class LIBPROTOBUF_EXPORT Arena { void AddListNode(void* elem, void (*cleanup)(void*)); // Delete or Destruct all objects owned by the arena. void CleanupList(); + uint64 ResetInternal(); inline void SetThreadCacheBlock(Block* block) { thread_cache().last_block_used_ = block; @@ -829,6 +873,9 @@ class LIBPROTOBUF_EXPORT Arena { Mutex blocks_lock_; void AddBlock(Block* b); + // Access must be synchronized, either by blocks_lock_ or by being called from + // Init()/Reset(). + void AddBlockInternal(Block* b); void* SlowAlloc(size_t n); Block* FindBlock(void* me); Block* NewBlock(void* me, Block* my_last_block, size_t n, @@ -854,6 +901,11 @@ const typename Arena::is_arena_constructable::type Arena::is_arena_constructable::value = typename Arena::is_arena_constructable::type(); +template +const typename Arena::is_destructor_skippable::type + Arena::is_destructor_skippable::value = + typename Arena::is_destructor_skippable::type(); + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/arena_test_util.cc b/src/google/protobuf/arena_test_util.cc index 21f55c6e..df9c5bd6 100644 --- a/src/google/protobuf/arena_test_util.cc +++ b/src/google/protobuf/arena_test_util.cc @@ -28,6 +28,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include #include #include diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc index 6c185695..c9ca1fd1 100644 --- a/src/google/protobuf/arena_unittest.cc +++ b/src/google/protobuf/arena_unittest.cc @@ -40,7 +40,9 @@ #include #include +#include #include +#include #include #include #include @@ -619,8 +621,6 @@ TEST(ArenaTest, RepeatedPtrFieldAddClearedTest) { } } -// N.B.: no reflection version of this test because all the arena-specific code -// is in RepeatedPtrField, and the reflection works implicitly based on that. TEST(ArenaTest, AddAllocatedToRepeatedField) { // Heap->arena case. Arena arena1; @@ -680,6 +680,55 @@ TEST(ArenaTest, AddAllocatedToRepeatedField) { } } +TEST(ArenaTest, AddAllocatedToRepeatedFieldViaReflection) { + // Heap->arena case. + Arena arena1; + TestAllTypes* arena1_message = Arena::CreateMessage(&arena1); + const Reflection* r = arena1_message->GetReflection(); + const Descriptor* d = arena1_message->GetDescriptor(); + const FieldDescriptor* fd = + d->FindFieldByName("repeated_nested_message"); + for (int i = 0; i < 10; i++) { + TestAllTypes::NestedMessage* heap_submessage = + new TestAllTypes::NestedMessage; + heap_submessage->set_bb(42); + r->AddAllocatedMessage(arena1_message, fd, heap_submessage); + // Should not copy object -- will use arena_->Own(). + EXPECT_EQ(heap_submessage, + &arena1_message->repeated_nested_message(i)); + EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb()); + } + + // Arena1->Arena2 case. + arena1_message->Clear(); + for (int i = 0; i < 10; i++) { + Arena arena2; + TestAllTypes::NestedMessage* arena2_submessage = + Arena::CreateMessage(&arena2); + arena2_submessage->set_bb(42); + r->AddAllocatedMessage(arena1_message, fd, arena2_submessage); + // Should copy object. + EXPECT_NE(arena2_submessage, + &arena1_message->repeated_nested_message(i)); + EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb()); + } + + // Arena->heap case. + TestAllTypes* heap_message = new TestAllTypes; + for (int i = 0; i < 10; i++) { + Arena arena2; + TestAllTypes::NestedMessage* arena2_submessage = + Arena::CreateMessage(&arena2); + arena2_submessage->set_bb(42); + r->AddAllocatedMessage(heap_message, fd, arena2_submessage); + // Should copy object. + EXPECT_NE(arena2_submessage, + &heap_message->repeated_nested_message(i)); + EXPECT_EQ(42, heap_message->repeated_nested_message(i).bb()); + } + delete heap_message; +} + TEST(ArenaTest, ReleaseLastRepeatedField) { // Release from arena-allocated repeated field and ensure that returned object // is heap-allocated. @@ -1230,7 +1279,7 @@ TEST(ArenaTest, ArenaHooksSanity) { EXPECT_EQ(1, ArenaHooksTestUtil::num_init); EXPECT_EQ(0, ArenaHooksTestUtil::num_allocations); ::google::protobuf::Arena::Create(&arena); - if (::google::protobuf::internal::has_trivial_destructor::value) { + if (google::protobuf::internal::has_trivial_destructor::value) { EXPECT_EQ(1, ArenaHooksTestUtil::num_allocations); } else { EXPECT_EQ(2, ArenaHooksTestUtil::num_allocations); diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h index d829ed91..1dacdc68 100755 --- a/src/google/protobuf/arenastring.h +++ b/src/google/protobuf/arenastring.h @@ -33,6 +33,7 @@ #include +#include #include #include @@ -145,7 +146,7 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr { // Swaps internal pointers. Arena-safety semantics: this is guarded by the // logic in Swap()/UnsafeArenaSwap() at the message level, so this method is // 'unsafe' if called directly. - inline void Swap(ArenaStringPtr* other) GOOGLE_ATTRIBUTE_ALWAYS_INLINE { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(ArenaStringPtr* other) { std::swap(ptr_, other->ptr_); } @@ -283,9 +284,8 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr { private: ::std::string* ptr_; - inline void CreateInstance(::google::protobuf::Arena* arena, - const ::std::string* initial_value) - GOOGLE_ATTRIBUTE_NOINLINE { + GOOGLE_ATTRIBUTE_NOINLINE void CreateInstance(::google::protobuf::Arena* arena, + const ::std::string* initial_value) { // Assumes ptr_ is not NULL. if (initial_value != NULL) { ptr_ = new ::std::string(*initial_value); @@ -296,8 +296,7 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr { arena->Own(ptr_); } } - inline void CreateInstanceNoArena(const ::std::string* initial_value) - GOOGLE_ATTRIBUTE_NOINLINE { + GOOGLE_ATTRIBUTE_NOINLINE void CreateInstanceNoArena(const ::std::string* initial_value) { if (initial_value != NULL) { ptr_ = new ::std::string(*initial_value); } else { diff --git a/src/google/protobuf/arenastring_unittest.cc b/src/google/protobuf/arenastring_unittest.cc index 8ebd4b9c..3fb582be 100644 --- a/src/google/protobuf/arenastring_unittest.cc +++ b/src/google/protobuf/arenastring_unittest.cc @@ -42,6 +42,7 @@ #endif #include +#include #include #include diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc index 0039b00a..473eb4e6 100644 --- a/src/google/protobuf/compiler/code_generator.cc +++ b/src/google/protobuf/compiler/code_generator.cc @@ -34,6 +34,7 @@ #include +#include #include #include diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index e8871861..26a4f0b0 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -1657,7 +1658,11 @@ bool CommandLineInterface::WriteDescriptorSet( &already_seen, file_set.mutable_file()); } } else { + set already_seen; for (int i = 0; i < parsed_files.size(); i++) { + if (!already_seen.insert(parsed_files[i]).second) { + continue; + } FileDescriptorProto* file_proto = file_set.add_file(); parsed_files[i]->CopyTo(file_proto); if (source_info_in_descriptor_set_) { diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index e5b77c33..46ea5c4e 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -886,6 +886,39 @@ TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) { EXPECT_FALSE(descriptor_set.file(0).has_source_code_info()); } +TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithDuplicates) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); + CreateTempFile("baz.proto", + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Baz {\n" + " optional Foo foo = 1;\n" + "}\n"); + + Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " + "--proto_path=$tmpdir bar.proto foo.proto bar.proto baz.proto"); + + ExpectNoErrors(); + + FileDescriptorSet descriptor_set; + ReadDescriptorSet("descriptor_set", &descriptor_set); + if (HasFatalFailure()) return; + EXPECT_EQ(3, descriptor_set.file_size()); + EXPECT_EQ("bar.proto", descriptor_set.file(0).name()); + EXPECT_EQ("foo.proto", descriptor_set.file(1).name()); + EXPECT_EQ("baz.proto", descriptor_set.file(2).name()); + // Descriptor set should not have source code info. + EXPECT_FALSE(descriptor_set.file(0).has_source_code_info()); +} + TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) { CreateTempFile("foo.proto", "syntax = \"proto2\";\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc index 13ed0b64..c3e9fe74 100644 --- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc @@ -133,8 +133,7 @@ TEST(BootstrapTest, GeneratedDescriptorMatches) { CppGenerator generator; MockGeneratorContext context; string error; - string parameter; - parameter = "dllexport_decl=LIBPROTOBUF_EXPORT"; + string parameter = "dllexport_decl=LIBPROTOBUF_EXPORT"; ASSERT_TRUE(generator.Generate(proto_file, parameter, &context, &error)); parameter = "dllexport_decl=LIBPROTOC_EXPORT"; diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc index 70d3a600..de4d7cc7 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc @@ -32,7 +32,6 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include #include #include @@ -70,14 +69,11 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, EnumGenerator::~EnumGenerator() {} -void EnumGenerator::GenerateForwardDeclaration(io::Printer* printer) { +void EnumGenerator::FillForwardDeclaration(set* enum_names) { if (!options_.proto_h) { return; } - map vars; - vars["classname"] = classname_; - printer->Print(vars, "enum $classname$ : int;\n"); - printer->Print(vars, "bool $classname$_IsValid(int value);\n"); + enum_names->insert(classname_); } void EnumGenerator::GenerateDefinition(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h index 3e930856..f3aa72e4 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum.h @@ -35,6 +35,7 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__ +#include #include #include #include @@ -60,11 +61,11 @@ class EnumGenerator { // Header stuff. - // Generate header code to forward-declare the enum. This is for use when + // Fills the name to use when declaring the enum. This is for use when // generating other .proto.h files. This code should be placed within the // enum's package namespace, but NOT within any class, even for nested // enums. - void GenerateForwardDeclaration(io::Printer* printer); + void FillForwardDeclaration(set* enum_names); // Generate header code defining the enum. This code should be placed // within the enum's package namespace, but NOT within any class, even for diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc index 965327b1..824e2205 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc @@ -35,7 +35,6 @@ #include #include #include -#include #include namespace google { diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc index 43df1d88..8d47d4e0 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_field.cc @@ -47,6 +47,7 @@ #include #include #include +#include #include #include diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index 1f0a8205..5dae4cdd 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -33,6 +33,7 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include +#include #include #ifndef _SHARED_PTR_H #include @@ -93,22 +94,36 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options) FileGenerator::~FileGenerator() {} -void FileGenerator::GenerateHeader(io::Printer* printer) { - GenerateTopHeaderGuard(printer); +void FileGenerator::GenerateProtoHeader(io::Printer* printer) { + if (!options_.proto_h) { + return; + } + + string filename_identifier = FilenameIdentifier(file_->name()); + GenerateTopHeaderGuard(printer, filename_identifier); + GenerateLibraryIncludes(printer); - GenerateDependencyIncludes(printer); + + for (int i = 0; i < file_->public_dependency_count(); i++) { + const FileDescriptor* dep = file_->public_dependency(i); + const char* extension = ".proto.h"; + string dependency = StripProto(dep->name()) + extension; + printer->Print( + "#include \"$dependency$\" // IWYU pragma: export\n", + "dependency", dependency); + } printer->Print( "// @@protoc_insertion_point(includes)\n"); + GenerateForwardDeclarations(printer); // Open namespace. GenerateNamespaceOpeners(printer); GenerateGlobalStateFunctionDeclarations(printer); - GenerateMessageForwardDeclarations(printer); printer->Print("\n"); @@ -133,6 +148,11 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { GenerateInlineFunctionDefinitions(printer); + printer->Print( + "\n" + "// @@protoc_insertion_point(namespace_scope)\n" + "\n"); + // Close up namespace. GenerateNamespaceClosers(printer); @@ -144,19 +164,89 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { "// @@protoc_insertion_point(global_scope)\n" "\n"); - GenerateBottomHeaderGuard(printer); + GenerateBottomHeaderGuard(printer, filename_identifier); +} + +void FileGenerator::GeneratePBHeader(io::Printer* printer) { + string filename_identifier = + FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : "")); + GenerateTopHeaderGuard(printer, filename_identifier); + + if (options_.proto_h) { + printer->Print("#include \"$basename$.proto.h\" // IWYU pragma: export\n", + "basename", StripProto(file_->name())); + } else { + GenerateLibraryIncludes(printer); + } + GenerateDependencyIncludes(printer); + + printer->Print( + "// @@protoc_insertion_point(includes)\n"); + + + + // Open namespace. + GenerateNamespaceOpeners(printer); + + if (!options_.proto_h) { + GenerateGlobalStateFunctionDeclarations(printer); + GenerateMessageForwardDeclarations(printer); + + printer->Print("\n"); + + GenerateEnumDefinitions(printer); + + printer->Print(kThickSeparator); + printer->Print("\n"); + + GenerateMessageDefinitions(printer); + + printer->Print("\n"); + printer->Print(kThickSeparator); + printer->Print("\n"); + + GenerateServiceDefinitions(printer); + + GenerateExtensionIdentifiers(printer); + + printer->Print("\n"); + printer->Print(kThickSeparator); + printer->Print("\n"); + + GenerateInlineFunctionDefinitions(printer); + } + + printer->Print( + "\n" + "// @@protoc_insertion_point(namespace_scope)\n"); + + // Close up namespace. + GenerateNamespaceClosers(printer); + + if (!options_.proto_h) { + // We need to specialize some templates in the ::google::protobuf namespace: + GenerateProto2NamespaceEnumSpecializations(printer); + } + + printer->Print( + "\n" + "// @@protoc_insertion_point(global_scope)\n" + "\n"); + + GenerateBottomHeaderGuard(printer, filename_identifier); } void FileGenerator::GenerateSource(io::Printer* printer) { + string header = + StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h"); printer->Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" "// source: $filename$\n" "\n" - // The generated code calls accessors that might be deprecated. We don't // want the compiler to warn in generated code. "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n" - "#include \"$basename$.pb.h\"\n" + "#include \"$header$\"\n" "\n" "#include \n" // for swap() "\n" @@ -165,7 +255,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) { "#include \n" "#include \n", "filename", file_->name(), - "basename", StripProto(file_->name())); + "header", header); // Unknown fields implementation in lite mode uses StringOutputStream if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) { @@ -181,6 +271,18 @@ void FileGenerator::GenerateSource(io::Printer* printer) { "#include \n"); } + if (options_.proto_h) { + // Use the smaller .proto.h files. + for (int i = 0; i < file_->dependency_count(); i++) { + const FileDescriptor* dep = file_->dependency(i); + const char* extension = ".proto.h"; + string dependency = StripProto(dep->name()) + extension; + printer->Print( + "#include \"$dependency$\"\n", + "dependency", dependency); + } + } + printer->Print( "// @@protoc_insertion_point(includes)\n"); @@ -276,6 +378,59 @@ void FileGenerator::GenerateSource(io::Printer* printer) { "// @@protoc_insertion_point(global_scope)\n"); } +class FileGenerator::ForwardDeclarations { + public: + ~ForwardDeclarations() { + for (map::iterator it = namespaces_.begin(), + end = namespaces_.end(); + it != end; ++it) { + delete it->second; + } + namespaces_.clear(); + } + + ForwardDeclarations* AddOrGetNamespace(const string& ns_name) { + ForwardDeclarations*& ns = namespaces_[ns_name]; + if (ns == NULL) { + ns = new ForwardDeclarations; + } + return ns; + } + + set& classes() { return classes_; } + set& enums() { return enums_; } + + void Print(io::Printer* printer) const { + for (set::const_iterator it = enums_.begin(), end = enums_.end(); + it != end; ++it) { + printer->Print("enum $enumname$ : int;\n" + "bool $enumname$_IsValid(int value);\n", + "enumname", it->c_str()); + } + for (set::const_iterator it = classes_.begin(), + end = classes_.end(); + it != end; ++it) { + printer->Print("class $classname$;\n", "classname", it->c_str()); + } + for (map::const_iterator + it = namespaces_.begin(), + end = namespaces_.end(); + it != end; ++it) { + printer->Print("namespace $nsname$ {\n", + "nsname", it->first); + it->second->Print(printer); + printer->Print("} // namespace $nsname$\n", + "nsname", it->first); + } + } + + + private: + map namespaces_; + set classes_; + set enums_; +}; + void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { // AddDescriptors() is a file-level procedure which adds the encoded // FileDescriptorProto for this .proto file to the global DescriptorPool for @@ -434,12 +589,17 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { string file_data; file_proto.SerializeToString(&file_data); +#ifdef _MSC_VER + bool breakdown_large_file = true; +#else + bool breakdown_large_file = false; +#endif // 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) { + if (breakdown_large_file && file_data.size() > 65535) { printer->Print( - "static const char descriptor[] = {\n"); + "static const char descriptor[] = {\n"); printer->Indent(); // Only write 25 bytes per line. @@ -447,26 +607,25 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { 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])); + "$char$, ", + "char", SimpleItoa(file_data[i])); } printer->Print( - "\n"); + "\n"); } printer->Outdent(); printer->Print( - "};\n"); + "};\n"); printer->Print( - "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n", - "size", SimpleItoa(file_data.size())); + "::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) { @@ -474,11 +633,10 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { "data", EscapeTrigraphs( CEscape(file_data.substr(i, kBytesPerLine)))); - } - printer->Print( - ", $size$);\n", + } + printer->Print( + ", $size$);\n", "size", SimpleItoa(file_data.size())); - } // Call MessageFactory::InternalRegisterGeneratedFile(). @@ -548,8 +706,40 @@ void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) { } } -void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer) { - string filename_identifier = FilenameIdentifier(file_->name()); +void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) { + ForwardDeclarations decls; + for (int i = 0; i < file_->dependency_count(); i++) { + FileGenerator dependency(file_->dependency(i), options_); + dependency.FillForwardDeclarations(&decls); + } + FillForwardDeclarations(&decls); + decls.Print(printer); +} + +void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) { + for (int i = 0; i < file_->public_dependency_count(); i++) { + FileGenerator dependency(file_->public_dependency(i), options_); + dependency.FillForwardDeclarations(decls); + } + for (int i = 0; i < package_parts_.size(); i++) { + decls = decls->AddOrGetNamespace(package_parts_[i]); + } + // Generate enum definitions. + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->FillEnumForwardDeclarations(&decls->enums()); + } + for (int i = 0; i < file_->enum_type_count(); i++) { + enum_generators_[i]->FillForwardDeclaration(&decls->enums()); + } + // Generate forward declarations of classes. + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->FillMessageForwardDeclarations( + &decls->classes()); + } +} + +void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer, + const string& filename_identifier) { // Generate top of header. printer->Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" @@ -564,8 +754,8 @@ void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer) { "filename_identifier", filename_identifier); } -void FileGenerator::GenerateBottomHeaderGuard(io::Printer* printer) { - string filename_identifier = FilenameIdentifier(file_->name()); +void FileGenerator::GenerateBottomHeaderGuard( + io::Printer* printer, const string& filename_identifier) { printer->Print( "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n", "filename_identifier", filename_identifier); @@ -696,9 +886,13 @@ void FileGenerator::GenerateGlobalStateFunctionDeclarations( } void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) { - // Generate forward declarations of classes. + set classes; for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateMessageForwardDeclaration(printer); + message_generators_[i]->FillMessageForwardDeclarations(&classes); + } + for (set::const_iterator it = classes.begin(), end = classes.end(); + it != end; ++it) { + printer->Print("class $classname$;\n", "classname", it->c_str()); } } @@ -804,10 +998,6 @@ void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) { // 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( diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h index e68f67bb..29cdaea5 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.h +++ b/src/google/protobuf/compiler/cpp/cpp_file.h @@ -69,10 +69,14 @@ class FileGenerator { const Options& options); ~FileGenerator(); - void GenerateHeader(io::Printer* printer); + void GenerateProtoHeader(io::Printer* printer); + void GeneratePBHeader(io::Printer* printer); void GenerateSource(io::Printer* printer); private: + // Internal type used by GenerateForwardDeclarations (defined in file.cc). + class ForwardDeclarations; + // Generate the BuildDescriptors() procedure, which builds all descriptors // for types defined in the file. void GenerateBuildDescriptors(io::Printer* printer); @@ -80,9 +84,19 @@ class FileGenerator { void GenerateNamespaceOpeners(io::Printer* printer); void GenerateNamespaceClosers(io::Printer* printer); + // For other imports, generates their forward-declarations. + void GenerateForwardDeclarations(io::Printer* printer); + + // Internal helper used by GenerateForwardDeclarations: fills 'decls' + // with all necessary forward-declarations for this file and its + // transient depednencies. + void FillForwardDeclarations(ForwardDeclarations* decls); + // Generates top or bottom of a header file. - void GenerateTopHeaderGuard(io::Printer* printer); - void GenerateBottomHeaderGuard(io::Printer* printer); + void GenerateTopHeaderGuard(io::Printer* printer, + const string& filename_identifier); + void GenerateBottomHeaderGuard(io::Printer* printer, + const string& filename_identifier); // Generates #include directives. void GenerateLibraryIncludes(io::Printer* printer); @@ -92,10 +106,20 @@ class FileGenerator { void GenerateGlobalStateFunctionDeclarations(io::Printer* printer); // Generates types for classes. - void GenerateMessageForwardDeclarations(io::Printer* printer); void GenerateMessageDefinitions(io::Printer* printer); + // Generates forward-declarations for just this file's classes. This is + // used for .pb.h headers, but not in proto_h mode. + void GenerateMessageForwardDeclarations(io::Printer* printer); + + // Fills in types for forward declarations. This is used internally, and + // also by other FileGenerators to determine imports' declarations. + void FillMessageForwardDeclarations(ForwardDeclarations* decls); + void FillMessageDefinitions(ForwardDeclarations* decls); + // Generates enum definitions. + void GenerateEnumForwardDeclarations(io::Printer* printer); + void FillEnumForwardDeclarations(ForwardDeclarations* decls); void GenerateEnumDefinitions(io::Printer* printer); // Generates generic service definitions. diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc index 99416372..781526b5 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.cc +++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc @@ -100,16 +100,23 @@ bool CppGenerator::Generate(const FileDescriptor* file, string basename = StripProto(file->name()); - basename.append(".pb"); FileGenerator file_generator(file, file_options); - // Generate header. + // Generate header(s). + if (file_options.proto_h) { + google::protobuf::scoped_ptr output( + generator_context->Open(basename + ".proto.h")); + io::Printer printer(output.get(), '$'); + file_generator.GenerateProtoHeader(&printer); + } + + basename.append(".pb"); { google::protobuf::scoped_ptr output( generator_context->Open(basename + ".h")); io::Printer printer(output.get(), '$'); - file_generator.GenerateHeader(&printer); + file_generator.GeneratePBHeader(&printer); } // Generate cc file. diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index 0f3688d0..678a995a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -39,6 +39,7 @@ #include #include +#include #include #include #include @@ -68,7 +69,7 @@ const char* const kKeywordList[] = { "constexpr", "const_cast", "continue", "decltype", "default", "delete", "do", "double", "dynamic_cast", "else", "enum", "explicit", "extern", "false", "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable", - "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator", "or", + "namespace", "new", "noexcept", "not", "not_eq", "NULL", "operator", "or", "or_eq", "private", "protected", "public", "register", "reinterpret_cast", "return", "short", "signed", "sizeof", "static", "static_assert", "static_cast", "struct", "switch", "template", "this", "thread_local", @@ -174,6 +175,14 @@ string SuperClassName(const Descriptor* descriptor) { "::google::protobuf::Message" : "::google::protobuf::MessageLite"; } +string DependentBaseDownCast() { + return "reinterpret_cast(this)->"; +} + +string DependentBaseConstDownCast() { + return "reinterpret_cast(this)->"; +} + string FieldName(const FieldDescriptor* field) { string result = field->name(); LowerString(&result); @@ -208,6 +217,19 @@ string FieldConstantName(const FieldDescriptor *field) { } bool IsFieldDependent(const FieldDescriptor* field) { + if (field->containing_oneof() != NULL && + field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + return true; + } + if (field->is_map()) { + const Descriptor* map_descriptor = field->message_type(); + for (int i = 0; i < map_descriptor->field_count(); i++) { + if (IsFieldDependent(map_descriptor->field(i))) { + return true; + } + } + return false; + } if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { return false; } diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index 4bbf8303..29c1f90b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -70,8 +70,15 @@ string ClassName(const EnumDescriptor* enum_descriptor, bool qualified); // This is a class name, like "ProtoName_InternalBase". string DependentBaseClassTemplateName(const Descriptor* descriptor); +// Name of the base class: either the dependent base class (for use with +// proto_h) or google::protobuf::Message. string SuperClassName(const Descriptor* descriptor); +// Returns a string that down-casts from the dependent base class to the +// derived class. +string DependentBaseDownCast(); +string DependentBaseConstDownCast(); + // Get the (unqualified) name that should be used for this field in C++ code. // The name is coerced to lower-case to emulate proto1 behavior. People // should be using lowercase-with-underscores style for proto field names diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc index 0ff0d27c..a14d8986 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc @@ -100,8 +100,9 @@ void SetMessageVariables(const FieldDescriptor* descriptor, MapFieldGenerator:: MapFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : descriptor_(descriptor) { + const Options& options) + : descriptor_(descriptor), + dependent_field_(options.proto_h && IsFieldDependent(descriptor)) { SetMessageVariables(descriptor, &variables_, options); } @@ -152,7 +153,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, void MapFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.Clear();\n"); + map variables(variables_); + variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : ""; + printer->Print(variables, "$this_message$$name$_.Clear();\n"); } void MapFieldGenerator:: diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h index d27d4851..5e205623 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h @@ -63,6 +63,7 @@ class MapFieldGenerator : public FieldGenerator { private: const FieldDescriptor* descriptor_; + const bool dependent_field_; map variables_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator); diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index b0e38755..aa10b0bb 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -39,7 +39,6 @@ #ifndef _SHARED_PTR_H #include #endif -#include #include #include #include @@ -415,31 +414,34 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor, use_dependent_base_ = true; } } + if (options.proto_h && descriptor->oneof_decl_count() > 0) { + // Always make oneofs dependent. + use_dependent_base_ = true; + } } MessageGenerator::~MessageGenerator() {} void MessageGenerator:: -GenerateMessageForwardDeclaration(io::Printer* printer) { - printer->Print("class $classname$;\n", - "classname", classname_); +FillMessageForwardDeclarations(set* class_names) { + class_names->insert(classname_); for (int i = 0; i < descriptor_->nested_type_count(); i++) { // map entry message doesn't need forward declaration. Since map entry // 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]->GenerateMessageForwardDeclaration(printer); + nested_generators_[i]->FillMessageForwardDeclarations(class_names); } } void MessageGenerator:: -GenerateEnumForwardDeclaration(io::Printer* printer) { +FillEnumForwardDeclarations(set* enum_names) { for (int i = 0; i < descriptor_->nested_type_count(); i++) { - nested_generators_[i]->GenerateEnumForwardDeclaration(printer); + nested_generators_[i]->FillEnumForwardDeclarations(enum_names); } for (int i = 0; i < descriptor_->enum_type_count(); i++) { - enum_generators_[i]->GenerateForwardDeclaration(printer); + enum_generators_[i]->FillForwardDeclaration(enum_names); } } @@ -484,13 +486,6 @@ GenerateDependentFieldAccessorDeclarations(io::Printer* printer) { 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:: @@ -505,7 +500,9 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { vars["constant_name"] = FieldConstantName(field); bool dependent_field = use_dependent_base_ && IsFieldDependent(field); - if (dependent_field) { + if (dependent_field && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !field->is_map()) { // 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: @@ -594,8 +591,8 @@ GenerateDependentFieldAccessorDefinitions(io::Printer* printer) { vars["tmpl"] = "template\n"; vars["dependent_classname"] = DependentBaseClassTemplateName(descriptor_) + ""; - vars["this_message"] = "reinterpret_cast(this)->"; - vars["this_const_message"] = "reinterpret_cast(this)->"; + vars["this_message"] = DependentBaseDownCast(); + vars["this_const_message"] = DependentBaseConstDownCast(); GenerateFieldClear(field, vars, printer); } @@ -721,13 +718,15 @@ GenerateFieldClear(const FieldDescriptor* field, printer->Print(vars, "if ($this_message$has_$name$()) {\n"); printer->Indent(); - field_generators_.get(field).GenerateClearingCode(printer); + 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); + field_generators_.get(field) + .GenerateClearingCode(printer); if (HasFieldPresence(descriptor_->file())) { if (!field->is_repeated()) { printer->Print(vars, @@ -752,6 +751,18 @@ GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) { map vars; SetCommonFieldVariables(field, &vars, options_); vars["inline"] = is_inline ? "inline " : ""; + if (use_dependent_base_ && IsFieldDependent(field)) { + vars["tmpl"] = "template\n"; + vars["dependent_classname"] = + DependentBaseClassTemplateName(descriptor_) + ""; + vars["this_message"] = "reinterpret_cast(this)->"; + vars["this_const_message"] = "reinterpret_cast(this)->"; + } else { + vars["tmpl"] = ""; + vars["dependent_classname"] = vars["classname"]; + vars["this_message"] = ""; + vars["this_const_message"] = ""; + } // Generate has_$name$() or $name$_size(). if (field->is_repeated()) { @@ -775,10 +786,6 @@ GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) { } if (!use_dependent_base_ || !IsFieldDependent(field)) { - vars["tmpl"] = ""; - vars["dependent_classname"] = vars["classname"]; - vars["this_message"] = ""; - vars["this_const_message"] = ""; GenerateFieldClear(field, vars, printer); } @@ -915,15 +922,32 @@ GenerateClassDefinition(io::Printer* printer) { "}\n" "\n"); } else { - printer->Print( - "inline const ::std::string& unknown_fields() const {\n" - " return _unknown_fields_;\n" - "}\n" - "\n" - "inline ::std::string* mutable_unknown_fields() {\n" - " return &_unknown_fields_;\n" - "}\n" - "\n"); + if (SupportsArenas(descriptor_)) { + printer->Print( + "inline const ::std::string& unknown_fields() const {\n" + " return _unknown_fields_.Get(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n" + "}\n" + "\n" + "inline ::std::string* mutable_unknown_fields() {\n" + " return _unknown_fields_.Mutable(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n" + " GetArenaNoVirtual());\n" + "}\n" + "\n"); + } else { + printer->Print( + "inline const ::std::string& unknown_fields() const {\n" + " return _unknown_fields_.GetNoArena(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n" + "}\n" + "\n" + "inline ::std::string* mutable_unknown_fields() {\n" + " return _unknown_fields_.MutableNoArena(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n" + "}\n" + "\n"); + } } } @@ -1068,6 +1092,10 @@ GenerateClassDefinition(io::Printer* printer) { } } uses_string_ = false; + if (PreserveUnknownFields(descriptor_) && + !UseUnknownFieldSet(descriptor_->file())) { + uses_string_ = true; + } for (int i = 0; i < descriptors.size(); i++) { const FieldDescriptor* field = descriptors[i]; if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { @@ -1201,18 +1229,11 @@ GenerateClassDefinition(io::Printer* printer) { // Generate oneof function declarations for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - 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()); - } + 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()) && @@ -1262,7 +1283,7 @@ GenerateClassDefinition(io::Printer* printer) { "::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;\n"); } else { printer->Print( - "::std::string _unknown_fields_;\n" + "::google::protobuf::internal::ArenaStringPtr _unknown_fields_;\n" "::google::protobuf::Arena* _arena_ptr_;\n" "\n"); } @@ -1919,6 +1940,13 @@ GenerateSharedConstructorCode(io::Printer* printer) { uses_string_ ? "::google::protobuf::internal::GetEmptyString();\n" : "", "_cached_size_ = 0;\n").c_str()); + if (PreserveUnknownFields(descriptor_) && + !UseUnknownFieldSet(descriptor_->file())) { + printer->Print( + "_unknown_fields_.UnsafeSetDefault(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"); + } + for (int i = 0; i < descriptor_->field_count(); i++) { if (!descriptor_->field(i)->containing_oneof()) { field_generators_.get(descriptor_->field(i)) @@ -1955,6 +1983,22 @@ GenerateSharedDestructorCode(io::Printer* printer) { "}\n" "\n"); } + + // Write the desctructor for _unknown_fields_ in lite runtime. + if (PreserveUnknownFields(descriptor_) && + !UseUnknownFieldSet(descriptor_->file())) { + if (SupportsArenas(descriptor_)) { + printer->Print( + "_unknown_fields_.Destroy(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n" + " GetArenaNoVirtual());\n"); + } else { + printer->Print( + "_unknown_fields_.DestroyNoArena(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"); + } + } + // Write the destructors for each field except oneof members. for (int i = 0; i < descriptor_->field_count(); i++) { if (!descriptor_->field(i)->containing_oneof()) { @@ -2463,8 +2507,16 @@ GenerateClear(io::Printer* printer) { " mutable_unknown_fields()->Clear();\n" "}\n"); } else { - printer->Print( - "mutable_unknown_fields()->clear();\n"); + if (SupportsArenas(descriptor_)) { + printer->Print( + "_unknown_fields_.ClearToEmpty(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n" + " GetArenaNoVirtual());\n"); + } else { + printer->Print( + "_unknown_fields_.ClearToEmptyNoArena(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"); + } } } @@ -2481,33 +2533,22 @@ GenerateOneofClear(io::Printer* printer) { oneof_vars["oneofname"] = descriptor_->oneof_decl(i)->name(); string message_class; - if (use_dependent_base_) { - oneof_vars["tmpl"] = "template\n"; - oneof_vars["inline"] = "inline "; - oneof_vars["dependent_classname"] = - DependentBaseClassTemplateName(descriptor_) + ""; - oneof_vars["this_message"] = "reinterpret_cast(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"); + "void $classname$::clear_$oneofname$() {\n"); printer->Indent(); + // In .proto.h mode, fields with a dependent type will generate + // clearing code that down casts from the dependent base class. + // However, clear_oneof() methods are always in the .cc file, and thus + // must remain in the derived base. So, to make the clearing code work, + // we add a typedef so that the down cast works (it will be a no-op). printer->Print(oneof_vars, - "switch($this_message$$oneofname$_case()) {\n"); + "typedef $classname$ T;\n" + "switch($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 $message_class$k$field_name$: {\n", - "message_class", message_class, + "case k$field_name$: {\n", "field_name", UnderscoresToCamelCase(field->name(), true)); printer->Indent(); // We clear only allocated objects in oneofs @@ -2524,20 +2565,16 @@ GenerateOneofClear(io::Printer* printer) { "}\n"); } printer->Print( - "case $message_class$$cap_oneof_name$_NOT_SET: {\n" + "case $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" - "$this_message$_oneof_case_[$oneof_index$] = " - "$message_class$$cap_oneof_name$_NOT_SET;\n", - "this_message", oneof_vars["this_message"], + "_oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n", "oneof_index", SimpleItoa(i), - "message_class", message_class, "cap_oneof_name", ToUpper(descriptor_->oneof_decl(i)->name())); printer->Outdent(); @@ -2612,7 +2649,7 @@ GenerateSwap(io::Printer* printer) { printer->Print( "_internal_metadata_.Swap(&other->_internal_metadata_);\n"); } else { - printer->Print("_unknown_fields_.swap(other->_unknown_fields_);\n"); + printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n"); } } else { // Still swap internal_metadata as it may contain more than just diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h index 23dad10c..8e19a3f0 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.h +++ b/src/google/protobuf/compiler/cpp/cpp_message.h @@ -39,8 +39,8 @@ #ifndef _SHARED_PTR_H #include #endif +#include #include -#include #include #include @@ -66,9 +66,10 @@ class MessageGenerator { // Header stuff. - // Generate foward declarations for this class and all its nested types. - void GenerateMessageForwardDeclaration(io::Printer* printer); - void GenerateEnumForwardDeclaration(io::Printer* printer); + // Return names for foward declarations of this class and all its nested + // types. + void FillMessageForwardDeclarations(set* class_names); + void FillEnumForwardDeclarations(set* enum_names); // Generate definitions of all nested enums (must come before class // definitions because those classes use the enums definitions). diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc index ba318d10..b4545892 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -63,6 +63,14 @@ void SetMessageVariables(const FieldDescriptor* descriptor, SafeFunctionName(descriptor->containing_type(), descriptor, "release_"); (*variables)["full_name"] = descriptor->full_name(); + if (options.proto_h && IsFieldDependent(descriptor)) { + (*variables)["dependent_type"] = "T::" + DependentTypeName(descriptor); + (*variables)["dependent_typename"] = + "typename T::" + DependentTypeName(descriptor); + } else { + (*variables)["dependent_type"] = FieldMessageTypeName(descriptor); + (*variables)["dependent_typename"] = FieldMessageTypeName(descriptor); + } } } // namespace @@ -84,8 +92,22 @@ GeneratePrivateMembers(io::Printer* printer) const { printer->Print(variables_, "$type$* $name$_;\n"); } +void MessageFieldGenerator:: +GenerateGetterDeclaration(io::Printer* printer) const { + printer->Print(variables_, + "const $type$& $name$() const$deprecation$;\n"); +} + void MessageFieldGenerator:: GenerateDependentAccessorDeclarations(io::Printer* printer) const { + if (!dependent_field_) { + return; + } + // Arena manipulation code is out-of-line in the derived message class. + printer->Print(variables_, + "$type$* mutable_$name$()$deprecation$;\n" + "$type$* $release_name$()$deprecation$;\n" + "void set_allocated_$name$($type$* $name$)$deprecation$;\n"); } void MessageFieldGenerator:: @@ -103,11 +125,13 @@ GenerateAccessorDeclarations(io::Printer* printer) const { "$type$* _slow_$release_name$()$deprecation$;\n" "public:\n"); } - printer->Print(variables_, - "const $type$& $name$() const$deprecation$;\n" - "$type$* mutable_$name$()$deprecation$;\n" - "$type$* $release_name$()$deprecation$;\n" - "void set_allocated_$name$($type$* $name$)$deprecation$;\n"); + GenerateGetterDeclaration(printer); + if (!dependent_field_) { + printer->Print(variables_, + "$type$* mutable_$name$()$deprecation$;\n" + "$type$* $release_name$()$deprecation$;\n" + "void set_allocated_$name$($type$* $name$)$deprecation$;\n"); + } if (SupportsArenas(descriptor_)) { printer->Print(variables_, "$type$* unsafe_arena_release_$name$()$deprecation$;\n" @@ -123,12 +147,12 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions( "void $classname$::_slow_mutable_$name$() {\n"); if (SupportsArenas(descriptor_->message_type())) { printer->Print(variables_, - " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n" - " GetArenaNoVirtual());\n"); + " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n" + " GetArenaNoVirtual());\n"); } else { printer->Print(variables_, - " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n" - " GetArenaNoVirtual());\n"); + " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n" + " GetArenaNoVirtual());\n"); } printer->Print(variables_, "}\n" @@ -151,7 +175,7 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions( 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_, + printer->Print(variables_, "void $classname$::_slow_set_allocated_$name$(\n" " ::google::protobuf::Arena* message_arena, $type$** $name$) {\n" " if (message_arena != NULL && \n" @@ -189,15 +213,139 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions( void MessageFieldGenerator:: GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { + if (!dependent_field_) { + return; + } + + map variables(variables_); + // For the CRTP base class, all mutation methods are dependent, and so + // they must be in the header. + variables["dependent_classname"] = + DependentBaseClassTemplateName(descriptor_->containing_type()) + ""; + variables["this_message"] = DependentBaseDownCast(); + if (!variables["set_hasbit"].empty()) { + variables["set_hasbit"] = + variables["this_message"] + variables["set_hasbit"]; + } + if (!variables["clear_hasbit"].empty()) { + variables["clear_hasbit"] = + variables["this_message"] + variables["clear_hasbit"]; + } + + if (SupportsArenas(descriptor_)) { + printer->Print(variables, + "template \n" + "inline $type$* $dependent_classname$::mutable_$name$() {\n" + " $set_hasbit$\n" + " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" + " if ($name$_ == NULL) {\n" + " $this_message$_slow_mutable_$name$();\n" + " }\n" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" + " return $name$_;\n" + "}\n" + "template \n" + "inline $type$* $dependent_classname$::$release_name$() {\n" + " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" + " $clear_hasbit$\n" + " if ($this_message$GetArenaNoVirtual() != NULL) {\n" + " return $this_message$_slow_$release_name$();\n" + " } else {\n" + " $dependent_typename$* temp = $name$_;\n" + " $name$_ = NULL;\n" + " return temp;\n" + " }\n" + "}\n" + "template \n" + "inline void $dependent_classname$::" + "set_allocated_$name$($type$* $name$) {\n" + " ::google::protobuf::Arena* message_arena = $this_message$GetArenaNoVirtual();\n" + " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" + " if (message_arena == NULL) {\n" + " delete $name$_;\n" + " }\n" + " if ($name$ != NULL) {\n"); + if (SupportsArenas(descriptor_->message_type())) { + // If we're on an arena and the incoming message is not, simply Own() it + // rather than copy to the arena -- either way we need a heap dealloc, + // 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, + " $this_message$_slow_set_allocated_$name$(message_arena, " + "&$name$);\n"); + } else { + printer->Print(variables, + " if (message_arena != NULL) {\n" + " message_arena->Own($name$);\n" + " }\n"); + } + printer->Print(variables, + " }\n" + " $name$_ = $name$;\n" + " if ($name$) {\n" + " $set_hasbit$\n" + " } else {\n" + " $clear_hasbit$\n" + " }\n" + // TODO(dlj): move insertion points to message class. + " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" + "}\n"); + } else { + printer->Print(variables, + "template \n" + "inline $type$* $dependent_classname$::mutable_$name$() {\n" + " $set_hasbit$\n" + " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" + " if ($name$_ == NULL) {\n" + " $name$_ = new $dependent_typename$;\n" + " }\n" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" + " return $name$_;\n" + "}\n" + "template \n" + "inline $type$* $dependent_classname$::$release_name$() {\n" + " $clear_hasbit$\n" + " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" + " $dependent_typename$* temp = $name$_;\n" + " $name$_ = NULL;\n" + " return temp;\n" + "}\n" + "template \n" + "inline void $dependent_classname$::" + "set_allocated_$name$($type$* $name$) {\n" + " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" + " delete $name$_;\n"); + + if (SupportsArenas(descriptor_->message_type())) { + printer->Print(variables, + " if ($name$ != NULL && static_cast< $dependent_typename$* >($name$)" + "->GetArena() != NULL) {\n" + " $dependent_typename$* new_$name$ = new $dependent_typename$;\n" + " new_$name$->CopyFrom(*$name$);\n" + " $name$ = new_$name$;\n" + " }\n"); + } + + printer->Print(variables, + " $name$_ = $name$;\n" + " if ($name$) {\n" + " $set_hasbit$\n" + " } else {\n" + " $clear_hasbit$\n" + " }\n" + " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" + "}\n"); + } } void MessageFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const { map variables(variables_); - variables["inline"] = is_inline ? "inline" : ""; + variables["inline"] = is_inline ? "inline " : ""; printer->Print(variables, - "$inline$ const $type$& $classname$::$name$() const {\n" + "$inline$const $type$& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n"); PrintHandlingOptionalStaticInitializers( @@ -206,19 +354,25 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n", // Without. " return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n"); + printer->Print(variables, "}\n"); + + if (dependent_field_) { + return; + } if (SupportsArenas(descriptor_)) { printer->Print(variables, - "}\n" - "$inline$ $type$* $classname$::mutable_$name$() {\n" + "$inline$" + "$type$* $classname$::mutable_$name$() {\n" " $set_hasbit$\n" " if ($name$_ == NULL) {\n" - " _slow_mutable_$name$();" + " _slow_mutable_$name$();\n" " }\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" " return _slow_$release_name$();\n" @@ -228,7 +382,8 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, " return temp;\n" " }\n" "}\n" - "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\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" @@ -260,8 +415,8 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, "}\n"); } else { 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" @@ -269,13 +424,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, " // @@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())) { @@ -301,15 +458,19 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, void MessageFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { + map variables(variables_); + variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : ""; if (!HasFieldPresence(descriptor_->file())) { // 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 (GetArenaNoVirtual() == NULL && $name$_ != NULL) delete $name$_;\n" - "$name$_ = NULL;\n"); + printer->Print(variables, + "if ($this_message$GetArenaNoVirtual() == NULL && " + "$this_message$$name$_ != NULL) delete $this_message$$name$_;\n" + "$this_message$$name$_ = NULL;\n"); } else { - printer->Print(variables_, - "if ($name$_ != NULL) $name$_->$type$::Clear();\n"); + printer->Print(variables, + "if ($this_message$$name$_ != NULL) $this_message$$name$_->" + "$dependent_type$::Clear();\n"); } } @@ -370,79 +531,149 @@ GenerateByteSize(io::Printer* printer) const { MessageOneofFieldGenerator:: MessageOneofFieldGenerator(const FieldDescriptor* descriptor, const Options& options) - : MessageFieldGenerator(descriptor, options) { + : MessageFieldGenerator(descriptor, options), + dependent_base_(options.proto_h) { SetCommonOneofFieldVariables(descriptor, &variables_); } MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} + +void MessageOneofFieldGenerator:: +GenerateDependentAccessorDeclarations(io::Printer* printer) const { + // Oneof field getters must be dependent as they call default_instance(). + // Otherwise, the logic is the same as MessageFields. + if (!dependent_field_) { + return; + } + printer->Print(variables_, + "const $type$& $name$() const$deprecation$;\n"); + MessageFieldGenerator::GenerateDependentAccessorDeclarations(printer); +} + +void MessageOneofFieldGenerator:: +GenerateGetterDeclaration(io::Printer* printer) const { + // Oneof field getters must be dependent as they call default_instance(). + // Unlike MessageField, this means there is no (non-dependent) getter to + // generate. + if (dependent_field_) { + return; + } + printer->Print(variables_, + "const $type$& $name$() const$deprecation$;\n"); +} + void MessageOneofFieldGenerator:: GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { + // For the CRTP base class, all mutation methods are dependent, and so + // they must be in the header. + if (!dependent_base_) { + return; + } + map variables(variables_); + variables["inline"] = "inline "; + variables["dependent_classname"] = + DependentBaseClassTemplateName(descriptor_->containing_type()) + ""; + variables["this_message"] = "reinterpret_cast(this)->"; + // Const message access is needed for the dependent getter. + variables["this_const_message"] = "reinterpret_cast(this)->"; + variables["tmpl"] = "template \n"; + variables["field_member"] = variables["this_message"] + + variables["oneof_prefix"] + variables["name"] + + "_"; + InternalGenerateInlineAccessorDefinitions(variables, printer); } void MessageOneofFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const { + if (dependent_base_) { + return; + } map variables(variables_); - variables["inline"] = is_inline ? "inline" : ""; + variables["inline"] = is_inline ? "inline " : ""; + variables["dependent_classname"] = variables["classname"]; + variables["this_message"] = ""; + variables["this_const_message"] = ""; + variables["tmpl"] = ""; + variables["field_member"] = + variables["oneof_prefix"] + variables["name"] + "_"; + variables["dependent_type"] = variables["type"]; + InternalGenerateInlineAccessorDefinitions(variables, printer); +} + +void MessageOneofFieldGenerator:: +GenerateNonInlineAccessorDefinitions(io::Printer* printer) const { + map variables(variables_); + variables["field_member"] = + variables["oneof_prefix"] + variables["name"] + "_"; + + //printer->Print(variables, +} + +void MessageOneofFieldGenerator:: +InternalGenerateInlineAccessorDefinitions(const map& variables, + io::Printer* printer) const { + printer->Print(variables, + "$tmpl$" + "$inline$ " + "const $type$& $dependent_classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return $this_const_message$has_$name$()\n" + " ? *$this_const_message$$oneof_prefix$$name$_\n" + " : $dependent_type$::default_instance();\n" + "}\n"); + if (SupportsArenas(descriptor_)) { 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" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n"); + "$tmpl$" + "$inline$" + "$type$* $dependent_classname$::mutable_$name$() {\n" + " if (!$this_message$has_$name$()) {\n" + " $this_message$clear_$oneof_name$();\n" + " $this_message$set_has_$name$();\n"); if (SupportsArenas(descriptor_->message_type())) { printer->Print(variables, - " $oneof_prefix$$name$_ = \n" - " ::google::protobuf::Arena::CreateMessage< $type$ >(\n" - " GetArenaNoVirtual());\n"); + " $field_member$ = \n" + " ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n" + " $this_message$GetArenaNoVirtual());\n"); } else { printer->Print(variables, - " $oneof_prefix$$name$_ = \n" - " ::google::protobuf::Arena::Create< $type$ >(\n" - " GetArenaNoVirtual());\n"); + " $this_message$$oneof_prefix$$name$_ = \n" + " ::google::protobuf::Arena::Create< $dependent_typename$ >(\n" + " $this_message$GetArenaNoVirtual());\n"); } printer->Print(variables, " }\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $oneof_prefix$$name$_;\n" + " return $field_member$;\n" "}\n" - "$inline$ $type$* $classname$::$release_name$() {\n" - " if (has_$name$()) {\n" - " clear_has_$oneof_name$();\n" - " if (GetArenaNoVirtual() != NULL) {\n" + "$tmpl$" + "$inline$" + "$type$* $dependent_classname$::$release_name$() {\n" + " if ($this_message$has_$name$()) {\n" + " $this_message$clear_has_$oneof_name$();\n" + " if ($this_message$GetArenaNoVirtual() != NULL) {\n" // N.B.: safe to use the underlying field pointer here because we are sure // that it is non-NULL (because has_$name$() returned true). - " $type$* temp = new $type$;\n" - " temp->MergeFrom(*$oneof_prefix$$name$_);\n" - " $oneof_prefix$$name$_ = NULL;\n" + " $dependent_typename$* temp = new $dependent_typename$;\n" + " temp->MergeFrom(*$field_member$);\n" + " $field_member$ = NULL;\n" " return temp;\n" " } else {\n" - " $type$* temp = $oneof_prefix$$name$_;\n" - " $oneof_prefix$$name$_ = NULL;\n" + " $dependent_typename$* temp = $field_member$;\n" + " $field_member$ = NULL;\n" " return temp;\n" " }\n" " } else {\n" " return NULL;\n" " }\n" "}\n" - "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n" - " if (has_$name$()) {\n" - " clear_has_$oneof_name$();\n" - " $type$* temp = $oneof_prefix$$name$_;\n" - " $oneof_prefix$$name$_ = NULL;\n" - " return temp;\n" - " } else {\n" - " return NULL;\n" - " }\n" - "}\n" - "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n" - " clear_$oneof_name$();\n" + "$tmpl$" + "$inline$" + "void $dependent_classname$::" + "set_allocated_$name$($type$* $name$) {\n" + " $this_message$clear_$oneof_name$();\n" " if ($name$) {\n"); if (SupportsArenas(descriptor_->message_type())) { @@ -450,32 +681,42 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, // 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. - " if (GetArenaNoVirtual() != NULL &&\n" + " if ($this_message$GetArenaNoVirtual() != NULL &&\n" " ::google::protobuf::Arena::GetArena($name$) == NULL) {\n" - " GetArenaNoVirtual()->Own($name$);\n" - " } else if (GetArenaNoVirtual() !=\n" + " $this_message$GetArenaNoVirtual()->Own($name$);\n" + " } else if ($this_message$GetArenaNoVirtual() !=\n" " ::google::protobuf::Arena::GetArena($name$)) {\n" - " $type$* new_$name$ = \n" - " ::google::protobuf::Arena::CreateMessage< $type$ >(\n" - " GetArenaNoVirtual());\n" + " $dependent_typename$* new_$name$ = \n" + " ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n" + " $this_message$GetArenaNoVirtual());\n" " new_$name$->CopyFrom(*$name$);\n" " $name$ = new_$name$;\n" " }\n"); } else { printer->Print(variables, - " if (GetArenaNoVirtual() != NULL) {\n" - " GetArenaNoVirtual()->Own($name$);\n" + " if ($this_message$GetArenaNoVirtual() != NULL) {\n" + " $this_message$GetArenaNoVirtual()->Own($name$);\n" " }\n"); } printer->Print(variables, - " set_has_$name$();\n" - " $oneof_prefix$$name$_ = $name$;\n" + " $this_message$set_has_$name$();\n" + " $field_member$ = $name$;\n" " }\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n" - "$inline$ void $classname$::unsafe_arena_set_allocated_$name$(" - "$type$* $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" + " $oneof_prefix$$name$_ = NULL;\n" + " return temp;\n" + " } else {\n" + " return NULL;\n" + " }\n" + "}\n" + "$inline$ void $classname$::unsafe_arena_set_allocated_$name$" + "($type$* $name$) {\n" // We rely on the oneof clear method to free the earlier contents of this // oneof. We can directly use the pointer we're given to set the new // value. @@ -489,44 +730,47 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, "}\n"); } else { 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" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_ = new $type$;\n" + "$tmpl$" + "$inline$" + "$type$* $dependent_classname$::mutable_$name$() {\n" + " if (!$this_message$has_$name$()) {\n" + " $this_message$clear_$oneof_name$();\n" + " $this_message$set_has_$name$();\n" + " $field_member$ = new $dependent_typename$;\n" " }\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $oneof_prefix$$name$_;\n" + " return $field_member$;\n" "}\n" - "$inline$ $type$* $classname$::$release_name$() {\n" - " if (has_$name$()) {\n" - " clear_has_$oneof_name$();\n" - " $type$* temp = $oneof_prefix$$name$_;\n" - " $oneof_prefix$$name$_ = NULL;\n" + "$tmpl$" + "$inline$" + "$type$* $dependent_classname$::$release_name$() {\n" + " if ($this_message$has_$name$()) {\n" + " $this_message$clear_has_$oneof_name$();\n" + " $dependent_typename$* temp = $field_member$;\n" + " $field_member$ = NULL;\n" " return temp;\n" " } else {\n" " return NULL;\n" " }\n" "}\n" - "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n" - " clear_$oneof_name$();\n" + "$tmpl$" + "$inline$" + "void $dependent_classname$::" + "set_allocated_$name$($type$* $name$) {\n" + " $this_message$clear_$oneof_name$();\n" " if ($name$) {\n"); if (SupportsArenas(descriptor_->message_type())) { printer->Print(variables, - " if ($name$->GetArena() != NULL) {\n" - " $type$* new_$name$ = new $type$;\n" + " if (static_cast< $dependent_typename$*>($name$)->" + "GetArena() != NULL) {\n" + " $dependent_typename$* new_$name$ = new $dependent_typename$;\n" " new_$name$->CopyFrom(*$name$);\n" " $name$ = new_$name$;\n" " }\n"); } printer->Print(variables, - " set_has_$name$();\n" - " $oneof_prefix$$name$_ = $name$;\n" + " $this_message$set_has_$name$();\n" + " $field_member$ = $name$;\n" " }\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n"); @@ -535,14 +779,16 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, void MessageOneofFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { + map variables(variables_); + variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : ""; if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - "if (GetArenaNoVirtual() == NULL) {\n" - " delete $oneof_prefix$$name$_;\n" + printer->Print(variables, + "if ($this_message$GetArenaNoVirtual() == NULL) {\n" + " delete $this_message$$oneof_prefix$$name$_;\n" "}\n"); } else { - printer->Print(variables_, - "delete $oneof_prefix$$name$_;\n"); + printer->Print(variables, + "delete $this_message$$oneof_prefix$$name$_;\n"); } } @@ -562,7 +808,9 @@ GenerateConstructorCode(io::Printer* printer) const { RepeatedMessageFieldGenerator:: RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Options& options) - : descriptor_(descriptor) { + : descriptor_(descriptor), + dependent_field_(options.proto_h && IsFieldDependent(descriptor)), + dependent_getter_(dependent_field_ && options.safe_boundary_check) { SetMessageVariables(descriptor, &variables_, options); } @@ -575,60 +823,160 @@ GeneratePrivateMembers(io::Printer* printer) const { } void RepeatedMessageFieldGenerator:: -GenerateDependentAccessorDeclarations(io::Printer* printer) const { -} - -void RepeatedMessageFieldGenerator:: -GenerateAccessorDeclarations(io::Printer* printer) const { +InternalGenerateTypeDependentAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "const $type$& $name$(int index) const$deprecation$;\n" "$type$* mutable_$name$(int index)$deprecation$;\n" "$type$* add_$name$()$deprecation$;\n"); + if (dependent_getter_) { + printer->Print(variables_, + "const ::google::protobuf::RepeatedPtrField< $type$ >&\n" + " $name$() const$deprecation$;\n"); + } printer->Print(variables_, - "const ::google::protobuf::RepeatedPtrField< $type$ >&\n" - " $name$() const$deprecation$;\n" "::google::protobuf::RepeatedPtrField< $type$ >*\n" " mutable_$name$()$deprecation$;\n"); } void RepeatedMessageFieldGenerator:: -GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { +GenerateDependentAccessorDeclarations(io::Printer* printer) const { + if (dependent_getter_) { + printer->Print(variables_, + "const $type$& $name$(int index) const$deprecation$;\n"); + } + if (dependent_field_) { + InternalGenerateTypeDependentAccessorDeclarations(printer); + } } void RepeatedMessageFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const { +GenerateAccessorDeclarations(io::Printer* printer) const { + if (!dependent_getter_) { + printer->Print(variables_, + "const $type$& $name$(int index) const$deprecation$;\n"); + } + if (!dependent_field_) { + InternalGenerateTypeDependentAccessorDeclarations(printer); + } + if (!dependent_getter_) { + printer->Print(variables_, + "const ::google::protobuf::RepeatedPtrField< $type$ >&\n" + " $name$() const$deprecation$;\n"); + } +} + +void RepeatedMessageFieldGenerator:: +GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { + if (!dependent_field_) { + return; + } map variables(variables_); - variables["inline"] = is_inline ? "inline" : ""; + // For the CRTP base class, all mutation methods are dependent, and so + // they must be in the header. + variables["dependent_classname"] = + DependentBaseClassTemplateName(descriptor_->containing_type()) + ""; + variables["this_message"] = DependentBaseDownCast(); + variables["this_const_message"] = DependentBaseConstDownCast(); + + if (dependent_getter_) { + printer->Print(variables, + "template \n" + "inline const $type$& $dependent_classname$::$name$(int index) const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return $this_const_message$$name$_.$cppget$(index);\n" + "}\n"); + } + + // Generate per-element accessors: 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" + "template \n" + "inline $type$* $dependent_classname$::mutable_$name$(int index) {\n" + // TODO(dlj): move insertion points " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $name$_.Mutable(index);\n" + " return $this_message$$name$_.Mutable(index);\n" "}\n" - "$inline$ $type$* $classname$::add_$name$() {\n" + "template \n" + "inline $type$* $dependent_classname$::add_$name$() {\n" " // @@protoc_insertion_point(field_add:$full_name$)\n" - " return $name$_.Add();\n" + " return $this_message$$name$_.Add();\n" "}\n"); + + + if (dependent_getter_) { + printer->Print(variables, + "template \n" + "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" + "$dependent_classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_list:$full_name$)\n" + " return $this_const_message$$name$_;\n" + "}\n"); + } + + // Generate mutable access to the entire list: 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" - "$classname$::mutable_$name$() {\n" + "template \n" + "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" + "$dependent_classname$::mutable_$name$() {\n" " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" - " return &$name$_;\n" + " return &$this_message$$name$_;\n" "}\n"); } +void RepeatedMessageFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map variables(variables_); + variables["inline"] = is_inline ? "inline " : ""; + + if (!dependent_getter_) { + 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"); + } + + if (!dependent_field_) { + printer->Print(variables, + "$inline$" + "$type$* $classname$::mutable_$name$(int index) {\n" + // TODO(dlj): move insertion points + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" + " return $name$_.Mutable(index);\n" + "}\n" + "$inline$" + "$type$* $classname$::add_$name$() {\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" + " return $name$_.Add();\n" + "}\n"); + } + + + if (!dependent_field_) { + printer->Print(variables, + "$inline$" + "::google::protobuf::RepeatedPtrField< $type$ >*\n" + "$classname$::mutable_$name$() {\n" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" + " return &$name$_;\n" + "}\n"); + } + if (!dependent_getter_) { + 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"); + } +} + void RepeatedMessageFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.Clear();\n"); + map variables(variables_); + variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : ""; + printer->Print(variables, "$this_message$$name$_.Clear();\n"); } void RepeatedMessageFieldGenerator:: diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h index 9ddf9643..35efd0fa 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h @@ -68,6 +68,11 @@ class MessageFieldGenerator : public FieldGenerator { void GenerateByteSize(io::Printer* printer) const; protected: + void GenerateArenaManipulationCode(const map& variables, + io::Printer* printer) const; + + virtual void GenerateGetterDeclaration(io::Printer* printer) const; + const FieldDescriptor* descriptor_; const bool dependent_field_; map variables_; @@ -83,15 +88,23 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator { ~MessageOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- + void GenerateDependentAccessorDeclarations(io::Printer* printer) const; void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const; void GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const; - void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {} + void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; + protected: + void GenerateGetterDeclaration(io::Printer* printer) const; + private: + void InternalGenerateInlineAccessorDefinitions( + const map& variables, io::Printer* printer) const; + + const bool dependent_base_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator); }; @@ -118,7 +131,12 @@ class RepeatedMessageFieldGenerator : public FieldGenerator { void GenerateByteSize(io::Printer* printer) const; private: + void InternalGenerateTypeDependentAccessorDeclarations( + io::Printer* printer) const; + const FieldDescriptor* descriptor_; + const bool dependent_field_; + const bool dependent_getter_; map variables_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index 1a3896a1..d1af6dda 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -421,7 +421,8 @@ GenerateByteSize(io::Printer* printer) const { StringOneofFieldGenerator:: StringOneofFieldGenerator(const FieldDescriptor* descriptor, const Options& options) - : StringFieldGenerator(descriptor, options) { + : StringFieldGenerator(descriptor, options), + dependent_field_(options.proto_h) { SetCommonOneofFieldVariables(descriptor, &variables_); } @@ -604,13 +605,29 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, void StringOneofFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { + map variables(variables_); + if (dependent_field_) { + variables["this_message"] = DependentBaseDownCast(); + // This clearing code may be in the dependent base class. If the default + // value is an empty string, then the $default_variable$ is a global + // singleton. If the default is not empty, we need to down-cast to get the + // default value's global singleton instance. See SetStringVariables() for + // possible values of default_variable. + if (!descriptor_->default_value_string().empty()) { + variables["default_variable"] = + DependentBaseDownCast() + variables["default_variable"]; + } + } else { + variables["this_message"] = ""; + } if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - "$oneof_prefix$$name$_.Destroy($default_variable$,\n" - " GetArenaNoVirtual());\n"); + printer->Print(variables, + "$this_message$$oneof_prefix$$name$_.Destroy($default_variable$,\n" + " $this_message$GetArenaNoVirtual());\n"); } else { - printer->Print(variables_, - "$oneof_prefix$$name$_.DestroyNoArena($default_variable$);\n"); + printer->Print(variables, + "$this_message$$oneof_prefix$$name$_." + "DestroyNoArena($default_variable$);\n"); } } @@ -664,7 +681,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { RepeatedStringFieldGenerator:: RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, const Options& options) - : descriptor_(descriptor) { + : descriptor_(descriptor) { SetStringVariables(descriptor, &variables_, options); } diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h index d1f19cd9..616e2067 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h @@ -93,6 +93,7 @@ class StringOneofFieldGenerator : public StringFieldGenerator { void GenerateMergeFromCodedStream(io::Printer* printer) const; private: + const bool dependent_field_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator); }; diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index bd1c0fde..e5ef6ecd 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -67,7 +67,9 @@ #include #include +#include #include +#include #include #include #include diff --git a/src/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc index 43eb0ed5..33c9328f 100644 --- a/src/google/protobuf/compiler/importer_unittest.cc +++ b/src/google/protobuf/compiler/importer_unittest.cc @@ -44,6 +44,7 @@ #include #include +#include #include #include #include diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc index 0353b607..8a09f3a8 100644 --- a/src/google/protobuf/compiler/java/java_enum.cc +++ b/src/google/protobuf/compiler/java/java_enum.cc @@ -181,8 +181,8 @@ void EnumGenerator::Generate(io::Printer* printer) { " internalGetValueMap() {\n" " return internalValueMap;\n" "}\n" - "private static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" - " internalValueMap =\n" + "private static final com.google.protobuf.Internal.EnumLiteMap<\n" + " $classname$> internalValueMap =\n" " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" " public $classname$ findValueByNumber(int number) {\n" " return $classname$.valueOf(number);\n" diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc index 39318a19..558da968 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.cc +++ b/src/google/protobuf/compiler/java/java_enum_field.cc @@ -35,6 +35,7 @@ #include #include +#include #include #include #include diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc index 697a07a7..2c3608c2 100644 --- a/src/google/protobuf/compiler/java/java_enum_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc @@ -35,6 +35,7 @@ #include #include +#include #include #include #include diff --git a/src/google/protobuf/compiler/java/java_enum_lite.cc b/src/google/protobuf/compiler/java/java_enum_lite.cc index e69de29b..62186386 100644 --- a/src/google/protobuf/compiler/java/java_enum_lite.cc +++ b/src/google/protobuf/compiler/java/java_enum_lite.cc @@ -0,0 +1,226 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +namespace { +bool EnumHasCustomOptions(const EnumDescriptor* descriptor) { + if (descriptor->options().unknown_fields().field_count() > 0) return true; + for (int i = 0; i < descriptor->value_count(); ++i) { + const EnumValueDescriptor* value = descriptor->value(i); + if (value->options().unknown_fields().field_count() > 0) return true; + } + return false; +} +} // namespace + +EnumLiteGenerator::EnumLiteGenerator(const EnumDescriptor* descriptor, + bool immutable_api, + Context* context) + : descriptor_(descriptor), immutable_api_(immutable_api), + name_resolver_(context->GetNameResolver()) { + for (int i = 0; i < descriptor_->value_count(); i++) { + const EnumValueDescriptor* value = descriptor_->value(i); + const EnumValueDescriptor* canonical_value = + descriptor_->FindValueByNumber(value->number()); + + if (value == canonical_value) { + canonical_values_.push_back(value); + } else { + Alias alias; + alias.value = value; + alias.canonical_value = canonical_value; + aliases_.push_back(alias); + } + } +} + +EnumLiteGenerator::~EnumLiteGenerator() {} + +void EnumLiteGenerator::Generate(io::Printer* printer) { + WriteEnumDocComment(printer, descriptor_); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public enum $classname$\n" + " implements com.google.protobuf.ProtocolMessageEnum {\n", + "classname", descriptor_->name()); + } else { + printer->Print( + "public enum $classname$\n" + " implements com.google.protobuf.Internal.EnumLite {\n", + "classname", descriptor_->name()); + } + printer->Indent(); + + for (int i = 0; i < canonical_values_.size(); i++) { + map vars; + vars["name"] = canonical_values_[i]->name(); + vars["index"] = SimpleItoa(canonical_values_[i]->index()); + vars["number"] = SimpleItoa(canonical_values_[i]->number()); + WriteEnumValueDocComment(printer, canonical_values_[i]); + if (canonical_values_[i]->options().deprecated()) { + printer->Print("@java.lang.Deprecated\n"); + } + printer->Print(vars, + "$name$($index$, $number$),\n"); + } + + if (SupportUnknownEnumValue(descriptor_->file())) { + printer->Print("UNRECOGNIZED(-1, -1),\n"); + } + + printer->Print( + ";\n" + "\n"); + + // ----------------------------------------------------------------- + + for (int i = 0; i < aliases_.size(); i++) { + map vars; + vars["classname"] = descriptor_->name(); + vars["name"] = aliases_[i].value->name(); + vars["canonical_name"] = aliases_[i].canonical_value->name(); + WriteEnumValueDocComment(printer, aliases_[i].value); + printer->Print(vars, + "public static final $classname$ $name$ = $canonical_name$;\n"); + } + + for (int i = 0; i < descriptor_->value_count(); i++) { + map vars; + vars["name"] = descriptor_->value(i)->name(); + vars["number"] = SimpleItoa(descriptor_->value(i)->number()); + WriteEnumValueDocComment(printer, descriptor_->value(i)); + printer->Print(vars, + "public static final int $name$_VALUE = $number$;\n"); + } + printer->Print("\n"); + + // ----------------------------------------------------------------- + + printer->Print( + "\n" + "public final int getNumber() {\n"); + if (SupportUnknownEnumValue(descriptor_->file())) { + printer->Print( + " if (index == -1) {\n" + " throw new java.lang.IllegalArgumentException(\n" + " \"Can't get the number of an unknown enum value.\");\n" + " }\n"); + } + printer->Print( + " return value;\n" + "}\n" + "\n" + "public static $classname$ valueOf(int value) {\n" + " switch (value) {\n", + "classname", descriptor_->name()); + printer->Indent(); + printer->Indent(); + + for (int i = 0; i < canonical_values_.size(); i++) { + printer->Print( + "case $number$: return $name$;\n", + "name", canonical_values_[i]->name(), + "number", SimpleItoa(canonical_values_[i]->number())); + } + + printer->Outdent(); + printer->Outdent(); + printer->Print( + " default: return null;\n" + " }\n" + "}\n" + "\n" + "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" + " internalGetValueMap() {\n" + " return internalValueMap;\n" + "}\n" + "private static final com.google.protobuf.Internal.EnumLiteMap<\n" + " $classname$> internalValueMap =\n" + " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" + " public $classname$ findValueByNumber(int number) {\n" + " return $classname$.valueOf(number);\n" + " }\n" + " };\n" + "\n", + "classname", descriptor_->name()); + + printer->Print( + "private final int value;\n\n" + "private $classname$(int index, int value) {\n", + "classname", descriptor_->name()); + printer->Print( + " this.value = value;\n" + "}\n"); + + printer->Print( + "\n" + "// @@protoc_insertion_point(enum_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); + + printer->Outdent(); + printer->Print("}\n\n"); +} + +bool EnumLiteGenerator::CanUseEnumValues() { + if (canonical_values_.size() != descriptor_->value_count()) { + return false; + } + for (int i = 0; i < descriptor_->value_count(); i++) { + if (descriptor_->value(i)->name() != canonical_values_[i]->name()) { + return false; + } + } + return true; +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_enum_lite.h b/src/google/protobuf/compiler/java/java_enum_lite.h index e69de29b..ee2f5f7a 100644 --- a/src/google/protobuf/compiler/java/java_enum_lite.h +++ b/src/google/protobuf/compiler/java/java_enum_lite.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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__ + +#include +#include +#include + +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 EnumLiteGenerator { + public: + explicit EnumLiteGenerator(const EnumDescriptor* descriptor, + bool immutable_api, + Context* context); + ~EnumLiteGenerator(); + + void Generate(io::Printer* printer); + + private: + const EnumDescriptor* descriptor_; + + // The proto language allows multiple enum constants to have the same numeric + // value. Java, however, does not allow multiple enum constants to be + // considered equivalent. We treat the first defined constant for any + // given numeric value as "canonical" and the rest as aliases of that + // canonical value. + vector canonical_values_; + + struct Alias { + const EnumValueDescriptor* value; + const EnumValueDescriptor* canonical_value; + }; + vector aliases_; + + bool immutable_api_; + + Context* context_; + ClassNameResolver* name_resolver_; + + bool CanUseEnumValues(); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumLiteGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc index 3f0fa11f..c5434767 100644 --- a/src/google/protobuf/compiler/java/java_field.cc +++ b/src/google/protobuf/compiler/java/java_field.cc @@ -39,6 +39,7 @@ #include #endif +#include #include #include #include diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h index 00f3c601..0e24da24 100644 --- a/src/google/protobuf/compiler/java/java_field.h +++ b/src/google/protobuf/compiler/java/java_field.h @@ -44,6 +44,7 @@ #include #include +#include namespace google { namespace protobuf { diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h index 96d2545f..99ba6a18 100644 --- a/src/google/protobuf/compiler/java/java_helpers.h +++ b/src/google/protobuf/compiler/java/java_helpers.h @@ -332,6 +332,10 @@ inline bool PreserveUnknownFields(const Descriptor* descriptor) { return descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3; } +inline bool IsAnyMessage(const Descriptor* descriptor) { + return descriptor->full_name() == "google.protobuf.Any"; +} + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc index 44b86cd7..3e035c89 100644 --- a/src/google/protobuf/compiler/java/java_map_field.cc +++ b/src/google/protobuf/compiler/java/java_map_field.cc @@ -314,6 +314,14 @@ GenerateBuilderMembers(io::Printer* printer) const { " internalGetMutable$capitalized_name$().getMutableMap(),\n" " $name$ValueConverter);\n" "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "$deprecation$public Builder putAll$capitalized_name$(\n" + " java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n" + " getMutable$capitalized_name$().putAll(values);\n" + " return this;\n" + "}\n"); if (SupportUnknownEnumValue(descriptor_->file())) { WriteFieldDocComment(printer, descriptor_); printer->Print( @@ -331,6 +339,14 @@ GenerateBuilderMembers(io::Printer* printer) const { "getMutable$capitalized_name$Value() {\n" " return internalGetMutable$capitalized_name$().getMutableMap();\n" "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "$deprecation$public Builder putAll$capitalized_name$Value(\n" + " java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n" + " getMutable$capitalized_name$Value().putAll(values);\n" + " return this;\n" + "}\n"); } } else { WriteFieldDocComment(printer, descriptor_); @@ -346,6 +362,14 @@ GenerateBuilderMembers(io::Printer* printer) const { "getMutable$capitalized_name$() {\n" " return internalGetMutable$capitalized_name$().getMutableMap();\n" "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "$deprecation$public Builder putAll$capitalized_name$(\n" + " java.util.Map<$type_parameters$> values) {\n" + " getMutable$capitalized_name$().putAll(values);\n" + " return this;\n" + "}\n"); } } diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc index cd1698f0..4fe656d3 100644 --- a/src/google/protobuf/compiler/java/java_map_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc @@ -303,6 +303,14 @@ GenerateBuilderMembers(io::Printer* printer) const { " copyOnWrite();\n" " return instance.getMutable$capitalized_name$();\n" "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "$deprecation$public Builder putAll$capitalized_name$(\n" + " java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n" + " getMutable$capitalized_name$().putAll(values);\n" + " return this;\n" + "}\n"); if (SupportUnknownEnumValue(descriptor_->file())) { WriteFieldDocComment(printer, descriptor_); printer->Print( @@ -321,6 +329,14 @@ GenerateBuilderMembers(io::Printer* printer) const { " copyOnWrite();\n" " return instance.getMutable$capitalized_name$Value();\n" "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "$deprecation$public Builder putAll$capitalized_name$Value(\n" + " java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n" + " getMutable$capitalized_name$Value().putAll(values);\n" + " return this;\n" + "}\n"); } } else { WriteFieldDocComment(printer, descriptor_); @@ -337,6 +353,14 @@ GenerateBuilderMembers(io::Printer* printer) const { " copyOnWrite();\n" " return instance.getMutable$capitalized_name$();\n" "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "public Builder putAll$capitalized_name$(\n" + " java.util.Map<$type_parameters$> values) {\n" + " getMutable$capitalized_name$().putAll(values);\n" + " return this;\n" + "}\n"); } } diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index 09b0fd94..80d6e9ad 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -255,6 +255,18 @@ void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { field_generators_.get(descriptor_->field(i)) .GenerateInterfaceMembers(printer); } + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "\n" + "public $classname$.$oneof_capitalized_name$Case " + "get$oneof_capitalized_name$Case();\n", + "oneof_capitalized_name", + context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name, + "classname", + context_->GetNameResolver()->GetImmutableClassName( + descriptor_)); + } printer->Outdent(); printer->Print("}\n"); @@ -292,8 +304,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { " com.google.protobuf.GeneratedMessage implements\n" " $extra_interfaces$\n" " $classname$OrBuilder {\n"); - - builder_type = "com.google.protobuf.GeneratedMessage.Builder"; + builder_type = "com.google.protobuf.GeneratedMessage.Builder"; } printer->Indent(); // Using builder_type, instead of Builder, prevents the Builder class from @@ -435,6 +446,10 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { "\n"); } + if (IsAnyMessage(descriptor_)) { + GenerateAnyMethods(printer); + } + // Fields for (int i = 0; i < descriptor_->field_count(); i++) { printer->Print("public static final int $constant_name$ = $number$;\n", @@ -578,9 +593,8 @@ GenerateMessageSerializationMethods(io::Printer* printer) { printer->Print( "}\n" "\n" - "private int memoizedSerializedSize = -1;\n" "public int getSerializedSize() {\n" - " int size = memoizedSerializedSize;\n" + " int size = memoizedSize;\n" " if (size != -1) return size;\n" "\n" " size = 0;\n"); @@ -612,7 +626,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) { printer->Outdent(); printer->Print( - " memoizedSerializedSize = size;\n" + " memoizedSize = size;\n" " return size;\n" "}\n" "\n"); @@ -948,22 +962,58 @@ GenerateEqualsAndHashCode(io::Printer* printer) { 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) { + if (field->containing_oneof() == NULL) { + 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"); + } + } + } + + // Compare oneofs. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "result = result && get$oneof_capitalized_name$Case().equals(\n" + " other.get$oneof_capitalized_name$Case());\n", + "oneof_capitalized_name", + context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name); + printer->Print( + "if (!result) return false;\n" + "switch ($oneof_name$Case_) {\n", + "oneof_name", + context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); printer->Print( - "result = result && (has$name$() == other.has$name$());\n" - "if (has$name$()) {\n", - "name", info->capitalized_name); + "case $field_number$:\n", + "field_number", + SimpleItoa(field->number())); printer->Indent(); - } - field_generators_.get(field).GenerateEqualsCode(printer); - if (check_has_bits) { + field_generators_.get(field).GenerateEqualsCode(printer); + printer->Print("break;\n"); printer->Outdent(); - printer->Print( - "}\n"); } + printer->Print( + "case 0:\n" + "default:\n"); + 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 @@ -1198,7 +1248,7 @@ GenerateParsingConstructor(io::Printer* printer) { // =================================================================== void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { printer->Print( - "public static final com.google.protobuf.Parser<$classname$> PARSER =\n" + "private static final com.google.protobuf.Parser<$classname$> PARSER =\n" " new com.google.protobuf.AbstractParser<$classname$>() {\n", "classname", descriptor_->name()); printer->Indent(); @@ -1250,6 +1300,10 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { "\n"); printer->Print( + "public static com.google.protobuf.Parser<$classname$> parser() {\n" + " return PARSER;\n" + "}\n" + "\n" "@java.lang.Override\n" "public com.google.protobuf.Parser<$classname$> getParserForType() {\n" " return PARSER;\n" @@ -1269,6 +1323,50 @@ void ImmutableMessageGenerator::GenerateInitializers(io::Printer* printer) { } +void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) { + printer->Print( + "private static String getTypeUrl(\n" + " com.google.protobuf.Descriptors.Descriptor descriptor) {\n" + " return \"type.googleapis.com/\" + descriptor.getFullName();\n" + "}\n" + "\n" + "public static Any pack(\n" + " T message) {\n" + " return Any.newBuilder()\n" + " .setTypeUrl(getTypeUrl(message.getDescriptorForType()))\n" + " .setValue(message.toByteString())\n" + " .build();\n" + "}\n" + "\n" + "public boolean is(\n" + " java.lang.Class clazz) {\n" + " T defaultInstance =\n" + " com.google.protobuf.Internal.getDefaultInstance(clazz);\n" + " return getTypeUrl().equals(\n" + " getTypeUrl(defaultInstance.getDescriptorForType()));\n" + "}\n" + "\n" + "private volatile com.google.protobuf.Message cachedUnpackValue;\n" + "\n" + "public T unpack(\n" + " java.lang.Class clazz)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " if (!is(clazz)) {\n" + " throw new com.google.protobuf.InvalidProtocolBufferException(\n" + " \"Type of the Any messsage does not match the given class.\");\n" + " }\n" + " if (cachedUnpackValue != null) {\n" + " return (T) cachedUnpackValue;\n" + " }\n" + " T defaultInstance =\n" + " com.google.protobuf.Internal.getDefaultInstance(clazz);\n" + " T result = (T) defaultInstance.getParserForType()\n" + " .parseFrom(getValue());\n" + " cachedUnpackValue = result;\n" + " return result;\n" + "}\n"); +} + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h index c3c37765..be5bfb07 100644 --- a/src/google/protobuf/compiler/java/java_message.h +++ b/src/google/protobuf/compiler/java/java_message.h @@ -122,6 +122,7 @@ class ImmutableMessageGenerator : public MessageGenerator { void GenerateEqualsAndHashCode(io::Printer* printer); void GenerateParser(io::Printer* printer); void GenerateParsingConstructor(io::Printer* printer); + void GenerateAnyMethods(io::Printer* printer); Context* context_; ClassNameResolver* name_resolver_; diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc index b180b4a7..b5f8e626 100644 --- a/src/google/protobuf/compiler/java/java_message_field.cc +++ b/src/google/protobuf/compiler/java/java_message_field.cc @@ -452,11 +452,11 @@ GenerateParsingCode(io::Printer* printer) const { if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { printer->Print(variables_, - "$name$_ = input.readGroup($number$, $type$.PARSER,\n" + "$name$_ = input.readGroup($number$, $type$.parser(),\n" " extensionRegistry);\n"); } else { printer->Print(variables_, - "$name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n"); + "$name$_ = input.readMessage($type$.parser(), extensionRegistry);\n"); } printer->Print(variables_, @@ -736,11 +736,12 @@ GenerateParsingCode(io::Printer* printer) const { if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { printer->Print(variables_, - "$oneof_name$_ = input.readGroup($number$, $type$.PARSER,\n" + "$oneof_name$_ = input.readGroup($number$, $type$.parser(),\n" " extensionRegistry);\n"); } else { printer->Print(variables_, - "$oneof_name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n"); + "$oneof_name$_ =\n" + " input.readMessage($type$.parser(), extensionRegistry);\n"); } printer->Print(variables_, @@ -1232,11 +1233,11 @@ GenerateParsingCode(io::Printer* printer) const { if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { printer->Print(variables_, - "$name$_.add(input.readGroup($number$, $type$.PARSER,\n" + "$name$_.add(input.readGroup($number$, $type$.parser(),\n" " extensionRegistry));\n"); } else { printer->Print(variables_, - "$name$_.add(input.readMessage($type$.PARSER, extensionRegistry));\n"); + "$name$_.add(input.readMessage($type$.parser(), extensionRegistry));\n"); } } diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.cc b/src/google/protobuf/compiler/java/java_message_field_lite.cc index 8332202c..356520ec 100644 --- a/src/google/protobuf/compiler/java/java_message_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc @@ -310,11 +310,11 @@ GenerateParsingCode(io::Printer* printer) const { if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { printer->Print(variables_, - "$name$_ = input.readGroup($number$, $type$.PARSER,\n" + "$name$_ = input.readGroup($number$, $type$.parser(),\n" " extensionRegistry);\n"); } else { printer->Print(variables_, - "$name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n"); + "$name$_ = input.readMessage($type$.parser(), extensionRegistry);\n"); } printer->Print(variables_, @@ -521,11 +521,12 @@ GenerateParsingCode(io::Printer* printer) const { if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { printer->Print(variables_, - "$oneof_name$_ = input.readGroup($number$, $type$.PARSER,\n" + "$oneof_name$_ = input.readGroup($number$, $type$.parser(),\n" " extensionRegistry);\n"); } else { printer->Print(variables_, - "$oneof_name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n"); + "$oneof_name$_ =\n" + " input.readMessage($type$.parser(), extensionRegistry);\n"); } printer->Print(variables_, @@ -885,11 +886,12 @@ GenerateParsingCode(io::Printer* printer) const { if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { printer->Print(variables_, - "$name$_.add(input.readGroup($number$, $type$.PARSER,\n" + "$name$_.add(input.readGroup($number$, $type$.parser(),\n" " extensionRegistry));\n"); } else { printer->Print(variables_, - "$name$_.add(input.readMessage($type$.PARSER, extensionRegistry));\n"); + "$name$_.add(\n" + " input.readMessage($type$.parser(), extensionRegistry));\n"); } } diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc index 3accee92..8b6c75b8 100644 --- a/src/google/protobuf/compiler/java/java_message_lite.cc +++ b/src/google/protobuf/compiler/java/java_message_lite.cc @@ -45,7 +45,7 @@ #include #include -#include +#include #include #include #include @@ -143,6 +143,17 @@ void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) { field_generators_.get(descriptor_->field(i)) .GenerateInterfaceMembers(printer); } + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "\n" + "public $classname$.$oneof_capitalized_name$Case " + "get$oneof_capitalized_name$Case();\n", + "oneof_capitalized_name", + context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name, + "classname", + context_->GetNameResolver()->GetImmutableClassName(descriptor_)); + } printer->Outdent(); printer->Print("}\n"); @@ -190,7 +201,7 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { // Nested types for (int i = 0; i < descriptor_->enum_type_count(); i++) { - EnumGenerator(descriptor_->enum_type(i), true, context_) + EnumLiteGenerator(descriptor_->enum_type(i), true, context_) .Generate(printer); } @@ -321,12 +332,12 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { printer->Print( "protected final Object dynamicMethod(\n" " com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n" - " Object... args) {\n" + " Object arg0, Object arg1) {\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" + " (com.google.protobuf.CodedInputStream) arg0,\n" + " (com.google.protobuf.ExtensionRegistryLite) arg1);\n" " }\n" " case NEW_INSTANCE: {\n" " return new $classname$(\n" @@ -370,7 +381,25 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { printer->Outdent(); printer->Print( - "}\n"); + "}\n" + "case GET_DEFAULT_INSTANCE: {\n" + " return DEFAULT_INSTANCE;\n" + "}\n" + "case GET_PARSER: {\n" + // Generally one would use the lazy initialization holder pattern for + // manipulating static fields but that has exceptional cost on Android as + // it will generate an extra class for every message. Instead, use the + // double-check locking pattern which works just as well. + " if (PARSER == null) {" + " synchronized ($classname$.class) {\n" + " if (PARSER == null) {\n" + " PARSER = new DefaultInstanceBasedParser(DEFAULT_INSTANCE);\n" + " }\n" + " }\n" + " }\n" + " return PARSER;\n" + "}\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Outdent(); printer->Outdent(); @@ -413,18 +442,6 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { 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. @@ -554,54 +571,54 @@ GenerateParseFromMethods(io::Printer* printer) { "public static $classname$ parseFrom(\n" " com.google.protobuf.ByteString data)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return PARSER.parseFrom(data);\n" + " return 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" + " 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" + " 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" + " 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" + " 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" + " 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" + " 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" + " 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" + " 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" + " return parser().parseFrom(input, extensionRegistry);\n" "}\n" "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); @@ -652,7 +669,7 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized( "if (isInitialized == 1) return DEFAULT_INSTANCE;\n" "if (isInitialized == 0) return null;\n" "\n" - "boolean shouldMemoize = ((Boolean) args[0]).booleanValue();\n"); + "boolean shouldMemoize = ((Boolean) arg0).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 @@ -778,7 +795,7 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMakeImmutable( .GenerateDynamicMethodMakeImmutableCode(printer); } printer->Print( - "return null;"); + "return null;\n"); } // =================================================================== @@ -786,7 +803,7 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMakeImmutable( void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuilder( io::Printer* printer) { printer->Print( - "return new Builder();"); + "return new Builder();\n"); } // =================================================================== @@ -796,9 +813,8 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom( 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", + "if (arg0 == $classname$.getDefaultInstance()) return this;\n" + "$classname$ other = ($classname$) arg0;\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); for (int i = 0; i < descriptor_->field_count(); i++) { @@ -1151,9 +1167,11 @@ GenerateParsingConstructor(io::Printer* printer) { // =================================================================== void ImmutableMessageLiteGenerator::GenerateParser(io::Printer* printer) { printer->Print( - "public static final com.google.protobuf.Parser<$classname$> PARSER =\n" - " new DefaultInstanceBasedParser(DEFAULT_INSTANCE);\n" - "\n", + "private static volatile com.google.protobuf.Parser<$classname$> PARSER;\n" + "\n" + "public static com.google.protobuf.Parser<$classname$> parser() {\n" + " return DEFAULT_INSTANCE.getParserForType();\n" + "}\n", "classname", descriptor_->name()); } diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc index 7bebe12a..178bbe19 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -35,6 +35,7 @@ #include #include +#include #include #include #include diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc index 217ff9b6..392333b8 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc @@ -35,6 +35,7 @@ #include #include +#include #include #include #include diff --git a/src/google/protobuf/compiler/java/java_service.cc b/src/google/protobuf/compiler/java/java_service.cc index 7baead15..11bfc12d 100644 --- a/src/google/protobuf/compiler/java/java_service.cc +++ b/src/google/protobuf/compiler/java/java_service.cc @@ -39,7 +39,6 @@ #include #include #include -#include #include namespace google { diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc index 68e863cc..47e04659 100644 --- a/src/google/protobuf/compiler/java/java_string_field.cc +++ b/src/google/protobuf/compiler/java/java_string_field.cc @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -77,6 +78,10 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, " if (value == null) {\n" " throw new NullPointerException();\n" " }\n"; + (*variables)["writeString"] = + "com.google.protobuf.GeneratedMessage.writeString"; + (*variables)["computeStringSize"] = + "com.google.protobuf.GeneratedMessage.computeStringSize"; // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler @@ -433,7 +438,7 @@ void ImmutableStringFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, "if ($is_field_present_message$) {\n" - " output.writeBytes($number$, get$capitalized_name$Bytes());\n" + " $writeString$(output, $number$, $name$_);\n" "}\n"); } @@ -441,8 +446,7 @@ void ImmutableStringFieldGenerator:: 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" + " size += $computeStringSize$($number$, $name$_);\n" "}\n"); } @@ -689,7 +693,7 @@ void ImmutableStringOneofFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, "if ($has_oneof_case_message$) {\n" - " output.writeBytes($number$, get$capitalized_name$Bytes());\n" + " $writeString$(output, $number$, $oneof_name$_);\n" "}\n"); } @@ -697,8 +701,7 @@ void ImmutableStringOneofFieldGenerator:: 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" + " size += $computeStringSize$($number$, $oneof_name$_);\n" "}\n"); } @@ -1007,12 +1010,12 @@ GenerateSerializationCode(io::Printer* printer) const { " output.writeRawVarint32($name$MemoizedSerializedSize);\n" "}\n" "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.write$capitalized_type$NoTag($name$_.get(i));\n" + " writeStringNoTag(output, $name$_.getRaw(i));\n" "}\n"); } else { printer->Print(variables_, "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.writeBytes($number$, $name$_.getByteString(i));\n" + " $writeString$(output, $number$, $name$_.getRaw(i));\n" "}\n"); } } @@ -1026,8 +1029,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, "for (int i = 0; i < $name$_.size(); i++) {\n" - " dataSize += com.google.protobuf.CodedOutputStream\n" - " .computeBytesSizeNoTag($name$_.getByteString(i));\n" + " dataSize += computeStringSizeNoTag($name$_.getRaw(i));\n" "}\n"); printer->Print( diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.cc b/src/google/protobuf/compiler/java/java_string_field_lite.cc index 51bb245c..032715b7 100644 --- a/src/google/protobuf/compiler/java/java_string_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -64,7 +65,8 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, map* variables) { SetCommonFieldVariables(descriptor, info, variables); - (*variables)["empty_list"] = "emptyLazyStringArrayList()"; + (*variables)["empty_list"] = + "com.google.protobuf.GeneratedMessageLite.emptyProtobufList()"; (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); (*variables)["default_init"] = @@ -101,7 +103,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, (*variables)["clear_has_field_bit_message"] = ""; (*variables)["is_field_present_message"] = - "!get" + (*variables)["capitalized_name"] + "Bytes().isEmpty()"; + "!get" + (*variables)["capitalized_name"] + ".isEmpty()"; } // For repeated builders, the underlying list tracks mutability state. @@ -144,8 +146,9 @@ 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: +// A note about how strings are handled. In the SPEED and CODE_SIZE runtimes, +// strings are not stored as java.lang.String in the Message because of two +// issues: // // 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded // strings, but rather fields that were raw bytes incorrectly marked @@ -160,22 +163,14 @@ int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const { // 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. +// In the LITE_RUNTIME, we store strings as java.lang.String because we assume +// that the users of this runtime are not subject to proto1 constraints and are +// running code on devices that are user facing. That is, the developers are +// properly incentivized to only fetch the data they need to read and wish to +// reduce the number of allocations incurred when running on a user's device. + +// TODO(dweis): Consider dropping all of the *Bytes() methods. They really +// shouldn't be necessary or used on devices. void ImmutableStringFieldLiteGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { @@ -195,7 +190,7 @@ GenerateInterfaceMembers(io::Printer* printer) const { void ImmutableStringFieldLiteGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private java.lang.Object $name$_;\n"); + "private java.lang.String $name$_;\n"); PrintExtraFieldInfo(variables_, printer); if (SupportFieldPresence(descriptor_->file())) { @@ -209,40 +204,13 @@ GenerateMembers(io::Printer* printer) const { 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" + " return $name$_;\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" + " return com.google.protobuf.ByteString.copyFromUtf8($name$_);\n" "}\n"); WriteFieldDocComment(printer, descriptor_); @@ -273,7 +241,7 @@ GenerateMembers(io::Printer* printer) const { } printer->Print(variables_, " $set_has_field_bit_message$\n" - " $name$_ = value;\n" + " $name$_ = value.toStringUtf8();\n" "}\n"); } @@ -368,7 +336,7 @@ GenerateParsingCode(io::Printer* printer) const { "String s = input.readStringRequireUtf8();\n" "$set_has_field_bit_message$\n" "$name$_ = s;\n"); - } else if (!HasDescriptorMethods(descriptor_->file())) { + } else { // 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 @@ -377,11 +345,6 @@ GenerateParsingCode(io::Printer* printer) const { "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"); } } @@ -392,18 +355,24 @@ GenerateParsingDoneCode(io::Printer* printer) const { void ImmutableStringFieldLiteGenerator:: GenerateSerializationCode(io::Printer* printer) const { + // Lite runtime should reduce allocations by serializing the string directly. + // This avoids spurious intermediary ByteString allocations, cutting overall + // allocations in half. printer->Print(variables_, "if ($is_field_present_message$) {\n" - " output.writeBytes($number$, get$capitalized_name$Bytes());\n" + " output.writeString($number$, get$capitalized_name$());\n" "}\n"); } void ImmutableStringFieldLiteGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { + // Lite runtime should reduce allocations by computing on the string directly. + // This avoids spurious intermediary ByteString allocations, cutting overall + // allocations in half. printer->Print(variables_, "if ($is_field_present_message$) {\n" " size += com.google.protobuf.CodedOutputStream\n" - " .computeBytesSize($number$, get$capitalized_name$Bytes());\n" + " .computeStringSize($number$, get$capitalized_name$());\n" "}\n"); } @@ -458,51 +427,22 @@ GenerateMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public java.lang.String get$capitalized_name$() {\n" - " java.lang.Object ref $default_init$;\n" + " java.lang.String 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" + " ref = (java.lang.String) $oneof_name$_;\n" " }\n" + " return ref;\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" + " java.lang.String 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" + " ref = (java.lang.String) $oneof_name$_;\n" " }\n" + " return com.google.protobuf.ByteString.copyFromUtf8(ref);\n" "}\n"); WriteFieldDocComment(printer, descriptor_); @@ -533,7 +473,7 @@ GenerateMembers(io::Printer* printer) const { } printer->Print(variables_, " $set_oneof_case_message$;\n" - " $oneof_name$_ = value;\n" + " $oneof_name$_ = value.toStringUtf8();\n" "}\n"); } @@ -603,7 +543,7 @@ GenerateParsingCode(io::Printer* printer) const { "String s = input.readStringRequireUtf8();\n" "$set_oneof_case_message$;\n" "$oneof_name$_ = s;\n"); - } else if (!HasDescriptorMethods(descriptor_->file())) { + } else { // 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 @@ -612,28 +552,29 @@ GenerateParsingCode(io::Printer* printer) const { "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 { + // Lite runtime should reduce allocations by serializing the string directly. + // This avoids spurious intermediary ByteString allocations, cutting overall + // allocations in half. printer->Print(variables_, "if ($has_oneof_case_message$) {\n" - " output.writeBytes($number$, get$capitalized_name$Bytes());\n" + " output.writeString($number$, get$capitalized_name$());\n" "}\n"); } void ImmutableStringOneofFieldLiteGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { + // Lite runtime should reduce allocations by computing on the string directly. + // This avoids spurious intermediary ByteString allocations, cutting overall + // allocations in half. printer->Print(variables_, "if ($has_oneof_case_message$) {\n" " size += com.google.protobuf.CodedOutputStream\n" - " .computeBytesSize($number$, get$capitalized_name$Bytes());\n" + " .computeStringSize($number$, get$capitalized_name$());\n" "}\n"); } @@ -667,7 +608,7 @@ void RepeatedImmutableStringFieldLiteGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$com.google.protobuf.ProtocolStringList\n" + "$deprecation$java.util.List\n" " get$capitalized_name$List();\n"); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, @@ -685,12 +626,11 @@ GenerateInterfaceMembers(io::Printer* printer) const { void RepeatedImmutableStringFieldLiteGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private com.google.protobuf.LazyStringArrayList $name$_;\n"); + "private com.google.protobuf.Internal.ProtobufList $name$_;\n"); PrintExtraFieldInfo(variables_, printer); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public com.google.protobuf.ProtocolStringList\n" - " get$capitalized_name$List() {\n" + "$deprecation$public java.util.List get$capitalized_name$List() {\n" " return $name$_;\n" // note: unmodifiable list "}\n"); WriteFieldDocComment(printer, descriptor_); @@ -707,7 +647,8 @@ GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "$deprecation$public com.google.protobuf.ByteString\n" " get$capitalized_name$Bytes(int index) {\n" - " return $name$_.getByteString(index);\n" + " return com.google.protobuf.ByteString.copyFromUtf8(\n" + " $name$_.get(index));\n" "}\n"); if (descriptor_->options().packed() && @@ -719,7 +660,8 @@ GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private void ensure$capitalized_name$IsMutable() {\n" " if (!$is_mutable$) {\n" - " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n" + " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList(\n" + " $name$_);\n" " }\n" "}\n"); @@ -764,7 +706,7 @@ GenerateMembers(io::Printer* printer) const { } printer->Print(variables_, " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(value);\n" + " $name$_.add(value.toStringUtf8());\n" "}\n"); } @@ -772,10 +714,10 @@ void RepeatedImmutableStringFieldLiteGenerator:: GenerateBuilderMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public com.google.protobuf.ProtocolStringList\n" + "$deprecation$public java.util.List\n" " get$capitalized_name$List() {\n" - " return ((com.google.protobuf.LazyStringList)\n" - " instance.get$capitalized_name$List()).getUnmodifiableView();\n" + " return java.util.Collections.unmodifiableList(\n" + " instance.get$capitalized_name$List());\n" "}\n"); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, @@ -875,20 +817,17 @@ GenerateParsingCode(io::Printer* printer) const { if (CheckUtf8(descriptor_)) { printer->Print(variables_, "String s = input.readStringRequireUtf8();\n"); - } else if (!HasDescriptorMethods(descriptor_->file())) { + } else { // 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" + " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList();\n" "}\n"); if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) { printer->Print(variables_, @@ -905,7 +844,7 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const { "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" + " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList();\n" "}\n" "while (input.getBytesUntilLimit() > 0) {\n"); if (CheckUtf8(descriptor_)) { @@ -932,6 +871,9 @@ GenerateParsingDoneCode(io::Printer* printer) const { void RepeatedImmutableStringFieldLiteGenerator:: GenerateSerializationCode(io::Printer* printer) const { + // Lite runtime should reduce allocations by serializing the string directly. + // This avoids spurious intermediary ByteString allocations, cutting overall + // allocations in half. if (descriptor_->options().packed()) { printer->Print(variables_, "if (get$capitalized_name$List().size() > 0) {\n" @@ -939,18 +881,21 @@ GenerateSerializationCode(io::Printer* printer) const { " output.writeRawVarint32($name$MemoizedSerializedSize);\n" "}\n" "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.write$capitalized_type$NoTag($name$_.get(i));\n" + " output.writeStringNoTag($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" + " output.writeString($number$, $name$_.get(i));\n" "}\n"); } } void RepeatedImmutableStringFieldLiteGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { + // Lite runtime should reduce allocations by computing on the string directly. + // This avoids spurious intermediary ByteString allocations, cutting overall + // allocations in half. printer->Print(variables_, "{\n" " int dataSize = 0;\n"); @@ -959,7 +904,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, "for (int i = 0; i < $name$_.size(); i++) {\n" " dataSize += com.google.protobuf.CodedOutputStream\n" - " .computeBytesSizeNoTag($name$_.getByteString(i));\n" + " .computeStringSizeNoTag($name$_.get(i));\n" "}\n"); printer->Print( diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index a2eeee2d..895ff34a 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h index 16012e96..007b001c 100644 --- a/src/google/protobuf/compiler/parser.h +++ b/src/google/protobuf/compiler/parser.h @@ -323,7 +323,7 @@ class LIBPROTOBUF_EXPORT Parser { const LocationRecorder& service_location, const FileDescriptorProto* containing_file); - // Parse one statement within a message, enum, or service block, inclunding + // Parse one statement within a message, enum, or service block, including // final semicolon. bool ParseMessageStatement(DescriptorProto* message, const LocationRecorder& message_location, @@ -364,7 +364,7 @@ class LIBPROTOBUF_EXPORT Parser { const LocationRecorder& extensions_location, const FileDescriptorProto* containing_file); - // Parse an "reserved" declaration. + // Parse a "reserved" declaration. bool ParseReserved(DescriptorProto* message, const LocationRecorder& message_location); bool ParseReservedNames(DescriptorProto* message, @@ -415,7 +415,7 @@ class LIBPROTOBUF_EXPORT Parser { Message* mutable_options); // Parse "required", "optional", or "repeated" and fill in "label" - // with the value. Returns true if shuch a label is consumed. + // with the value. Returns true if such a label is consumed. bool ParseLabel(FieldDescriptorProto::Label* label, const FileDescriptorProto* containing_file); diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc index cdcaffde..2bebf1f3 100644 --- a/src/google/protobuf/compiler/plugin.cc +++ b/src/google/protobuf/compiler/plugin.cc @@ -48,6 +48,7 @@ #include #endif +#include #include #include #include diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index e7890fae..994bc392 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -629,28 +629,28 @@ int CodeGeneratorRequest::proto_file_size() const { void CodeGeneratorRequest::clear_proto_file() { proto_file_.Clear(); } - const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const { +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) { +::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() { +::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 >* +::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_; } +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_; +} #endif // PROTOBUF_INLINE_NOT_IN_HEADERS @@ -1535,28 +1535,28 @@ int CodeGeneratorResponse::file_size() const { void CodeGeneratorResponse::clear_file() { file_.Clear(); } - const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* CodeGeneratorResponse::mutable_file() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file) return &file_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& +CodeGeneratorResponse::file() const { + // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file) + return file_; +} #endif // PROTOBUF_INLINE_NOT_IN_HEADERS diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index 6fcaea2e..ab79bdae 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -144,10 +144,10 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* mutable_proto_file(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& + proto_file() const; // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest) private: @@ -378,10 +378,10 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* mutable_file(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& + file() const; // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse) private: @@ -534,16 +534,16 @@ inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_ // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return proto_file_.Add(); } -inline 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_; -} inline ::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_; } +inline 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_; +} // ------------------------------------------------------------------- @@ -784,16 +784,16 @@ inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorRe // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file) return file_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& -CodeGeneratorResponse::file() const { - // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file) - return file_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* CodeGeneratorResponse::mutable_file() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file) return &file_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& +CodeGeneratorResponse::file() const { + // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file) + return file_; +} #endif // !PROTOBUF_INLINE_NOT_IN_HEADERS // ------------------------------------------------------------------- diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc index 7b3b5fa3..4d500f90 100644 --- a/src/google/protobuf/compiler/python/python_generator.cc +++ b/src/google/protobuf/compiler/python/python_generator.cc @@ -58,6 +58,7 @@ #include #include +#include #include #include #include diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h index 2ddac601..aa0f5fce 100644 --- a/src/google/protobuf/compiler/python/python_generator.h +++ b/src/google/protobuf/compiler/python/python_generator.h @@ -38,6 +38,7 @@ #include #include +#include #include namespace google { diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc index a3cff1f8..85429924 100644 --- a/src/google/protobuf/compiler/subprocess.cc +++ b/src/google/protobuf/compiler/subprocess.cc @@ -42,6 +42,7 @@ #include #endif +#include #include #include #include diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index 2855c377..5256b83c 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -53,6 +53,8 @@ #include #include #include +#include +#include #include #include #include @@ -1092,6 +1094,7 @@ const DescriptorPool* DescriptorPool::generated_pool() { return generated_pool_; } + DescriptorPool* DescriptorPool::internal_generated_pool() { InitGeneratedPoolOnce(); return generated_pool_; @@ -3699,6 +3702,14 @@ static bool ExistingFileMatchesProto(const FileDescriptor* existing_file, const FileDescriptorProto& proto) { FileDescriptorProto existing_proto; existing_file->CopyTo(&existing_proto); + // TODO(liujisi): Remove it when CopyTo supports copying syntax params when + // syntax="proto2". + if (existing_file->syntax() == FileDescriptor::SYNTAX_PROTO2 && + proto.has_syntax()) { + existing_proto.set_syntax( + existing_file->SyntaxName(existing_file->syntax())); + } + return existing_proto.SerializeAsString() == proto.SerializeAsString(); } @@ -4649,7 +4660,7 @@ void DescriptorBuilder::CrossLinkMessage( // safe. if (oneof_decl->field_count() > 0 && message->field(i - 1)->containing_oneof() != oneof_decl) { - AddWarning( + AddError( message->full_name() + "." + message->field(i - 1)->name(), proto.field(i - 1), DescriptorPool::ErrorCollector::OTHER, strings::Substitute( @@ -5088,8 +5099,7 @@ 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) { + if (field->type() == FieldDescriptor::TYPE_GROUP) { AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, "Groups are not supported in proto3 syntax."); @@ -5307,6 +5317,14 @@ bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field, // are added. } + if (value->type() == FieldDescriptor::TYPE_ENUM) { + if (value->enum_type()->value(0)->number() != 0) { + AddError( + field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "Enum value in map must define 0 as the first value."); + } + } + return true; } diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index ca87d634..2ab316a5 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h @@ -58,6 +58,7 @@ #include #include #include +#include // TYPE_BOOL is defined in the MacOS's ConditionalMacros.h. #ifdef TYPE_BOOL @@ -860,7 +861,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptor { friend class FieldDescriptor; friend class EnumValueDescriptor; friend class FileDescriptor; - friend class LIBPROTOBUF_EXPORT internal::GeneratedMessageReflection; + friend class internal::GeneratedMessageReflection; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumDescriptor); }; @@ -1332,6 +1333,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // this pool. Do not add your own descriptors to this pool. static const DescriptorPool* generated_pool(); + // Find a FileDescriptor in the pool by file name. Returns NULL if not // found. const FileDescriptor* FindFileByName(const string& name) const; diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 5e7eeaa7..6f9905aa 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -755,9 +755,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "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" + "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); + "PB", 4962); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); @@ -1066,28 +1066,28 @@ int FileDescriptorSet::file_size() const { void FileDescriptorSet::clear_file() { file_.Clear(); } - const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* FileDescriptorSet::mutable_file() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file) return &file_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& +FileDescriptorSet::file() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file) + return file_; +} #endif // PROTOBUF_INLINE_NOT_IN_HEADERS @@ -2091,28 +2091,28 @@ int FileDescriptorProto::message_type_size() const { void FileDescriptorProto::clear_message_type() { message_type_.Clear(); } - const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* FileDescriptorProto::mutable_message_type() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type) return &message_type_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& +FileDescriptorProto::message_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type) + return message_type_; +} // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; int FileDescriptorProto::enum_type_size() const { @@ -2121,28 +2121,28 @@ int FileDescriptorProto::enum_type_size() const { void FileDescriptorProto::clear_enum_type() { enum_type_.Clear(); } - const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* FileDescriptorProto::mutable_enum_type() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type) return &enum_type_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& +FileDescriptorProto::enum_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type) + return enum_type_; +} // repeated .google.protobuf.ServiceDescriptorProto service = 6; int FileDescriptorProto::service_size() const { @@ -2151,28 +2151,28 @@ int FileDescriptorProto::service_size() const { void FileDescriptorProto::clear_service() { service_.Clear(); } - const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* FileDescriptorProto::mutable_service() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service) return &service_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& +FileDescriptorProto::service() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service) + return service_; +} // repeated .google.protobuf.FieldDescriptorProto extension = 7; int FileDescriptorProto::extension_size() const { @@ -2181,28 +2181,28 @@ int FileDescriptorProto::extension_size() const { void FileDescriptorProto::clear_extension() { extension_.Clear(); } - const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* FileDescriptorProto::mutable_extension() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension) return &extension_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +FileDescriptorProto::extension() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension) + return extension_; +} // optional .google.protobuf.FileOptions options = 8; bool FileDescriptorProto::has_options() const { @@ -2218,11 +2218,11 @@ void FileDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear(); clear_has_options(); } - const ::google::protobuf::FileOptions& FileDescriptorProto::options() const { +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() { +::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() { set_has_options(); if (options_ == NULL) { options_ = new ::google::protobuf::FileOptions; @@ -2230,13 +2230,13 @@ void FileDescriptorProto::clear_options() { // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options) return options_; } - ::google::protobuf::FileOptions* FileDescriptorProto::release_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) { +void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) { delete options_; options_ = options; if (options) { @@ -2261,11 +2261,11 @@ 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 { +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() { +::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; @@ -2273,13 +2273,13 @@ void FileDescriptorProto::clear_source_code_info() { // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info) return source_code_info_; } - ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_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) { +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) { @@ -3720,28 +3720,28 @@ int DescriptorProto::field_size() const { void DescriptorProto::clear_field() { field_.Clear(); } - const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* DescriptorProto::mutable_field() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field) return &field_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +DescriptorProto::field() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field) + return field_; +} // repeated .google.protobuf.FieldDescriptorProto extension = 6; int DescriptorProto::extension_size() const { @@ -3750,28 +3750,28 @@ int DescriptorProto::extension_size() const { void DescriptorProto::clear_extension() { extension_.Clear(); } - const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* DescriptorProto::mutable_extension() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension) return &extension_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +DescriptorProto::extension() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension) + return extension_; +} // repeated .google.protobuf.DescriptorProto nested_type = 3; int DescriptorProto::nested_type_size() const { @@ -3780,28 +3780,28 @@ int DescriptorProto::nested_type_size() const { void DescriptorProto::clear_nested_type() { nested_type_.Clear(); } - const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* DescriptorProto::mutable_nested_type() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type) return &nested_type_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& +DescriptorProto::nested_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type) + return nested_type_; +} // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; int DescriptorProto::enum_type_size() const { @@ -3810,28 +3810,28 @@ int DescriptorProto::enum_type_size() const { void DescriptorProto::clear_enum_type() { enum_type_.Clear(); } - const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* DescriptorProto::mutable_enum_type() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type) return &enum_type_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& +DescriptorProto::enum_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type) + return enum_type_; +} // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; int DescriptorProto::extension_range_size() const { @@ -3840,28 +3840,28 @@ int DescriptorProto::extension_range_size() const { void DescriptorProto::clear_extension_range() { extension_range_.Clear(); } - const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const { +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) { +::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() { +::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 >* +::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_; } +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_; +} // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; int DescriptorProto::oneof_decl_size() const { @@ -3870,28 +3870,28 @@ int DescriptorProto::oneof_decl_size() const { void DescriptorProto::clear_oneof_decl() { oneof_decl_.Clear(); } - const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >* DescriptorProto::mutable_oneof_decl() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl) return &oneof_decl_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& +DescriptorProto::oneof_decl() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_; +} // optional .google.protobuf.MessageOptions options = 7; bool DescriptorProto::has_options() const { @@ -3907,11 +3907,11 @@ void DescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear(); clear_has_options(); } - const ::google::protobuf::MessageOptions& DescriptorProto::options() const { +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() { +::google::protobuf::MessageOptions* DescriptorProto::mutable_options() { set_has_options(); if (options_ == NULL) { options_ = new ::google::protobuf::MessageOptions; @@ -3919,13 +3919,13 @@ void DescriptorProto::clear_options() { // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options) return options_; } - ::google::protobuf::MessageOptions* DescriptorProto::release_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) { +void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) { delete options_; options_ = options; if (options) { @@ -3943,28 +3943,28 @@ int DescriptorProto::reserved_range_size() const { void DescriptorProto::clear_reserved_range() { reserved_range_.Clear(); } - const ::google::protobuf::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const { +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) { +::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() { +::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 >* +::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_; } +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_; +} // repeated string reserved_name = 10; int DescriptorProto::reserved_name_size() const { @@ -5062,11 +5062,11 @@ void FieldDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear(); clear_has_options(); } - const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const { +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() { +::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() { set_has_options(); if (options_ == NULL) { options_ = new ::google::protobuf::FieldOptions; @@ -5074,13 +5074,13 @@ void FieldDescriptorProto::clear_options() { // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options) return options_; } - ::google::protobuf::FieldOptions* FieldDescriptorProto::release_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) { +void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) { delete options_; options_ = options; if (options) { @@ -5804,28 +5804,28 @@ int EnumDescriptorProto::value_size() const { void EnumDescriptorProto::clear_value() { value_.Clear(); } - const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* EnumDescriptorProto::mutable_value() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value) return &value_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& +EnumDescriptorProto::value() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value) + return value_; +} // optional .google.protobuf.EnumOptions options = 3; bool EnumDescriptorProto::has_options() const { @@ -5841,11 +5841,11 @@ void EnumDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear(); clear_has_options(); } - const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const { +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() { +::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() { set_has_options(); if (options_ == NULL) { options_ = new ::google::protobuf::EnumOptions; @@ -5853,13 +5853,13 @@ void EnumDescriptorProto::clear_options() { // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options) return options_; } - ::google::protobuf::EnumOptions* EnumDescriptorProto::release_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) { +void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) { delete options_; options_ = options; if (options) { @@ -6304,11 +6304,11 @@ void EnumValueDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear(); clear_has_options(); } - const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const { +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() { +::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() { set_has_options(); if (options_ == NULL) { options_ = new ::google::protobuf::EnumValueOptions; @@ -6316,13 +6316,13 @@ void EnumValueDescriptorProto::clear_options() { // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options) return options_; } - ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_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) { +void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) { delete options_; options_ = options; if (options) { @@ -6740,28 +6740,28 @@ int ServiceDescriptorProto::method_size() const { void ServiceDescriptorProto::clear_method() { method_.Clear(); } - const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* ServiceDescriptorProto::mutable_method() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method) return &method_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& +ServiceDescriptorProto::method() const { + // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method) + return method_; +} // optional .google.protobuf.ServiceOptions options = 3; bool ServiceDescriptorProto::has_options() const { @@ -6777,11 +6777,11 @@ void ServiceDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear(); clear_has_options(); } - const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const { +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() { +::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() { set_has_options(); if (options_ == NULL) { options_ = new ::google::protobuf::ServiceOptions; @@ -6789,13 +6789,13 @@ void ServiceDescriptorProto::clear_options() { // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options) return options_; } - ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_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) { +void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) { delete options_; options_ = options; if (options) { @@ -7480,11 +7480,11 @@ void MethodDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear(); clear_has_options(); } - const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const { +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() { +::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() { set_has_options(); if (options_ == NULL) { options_ = new ::google::protobuf::MethodOptions; @@ -7492,13 +7492,13 @@ void MethodDescriptorProto::clear_options() { // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options) return options_; } - ::google::protobuf::MethodOptions* MethodDescriptorProto::release_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) { +void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) { delete options_; options_ = options; if (options) { @@ -9025,28 +9025,28 @@ int FileOptions::uninterpreted_option_size() const { void FileOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } - const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* FileOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option) return &uninterpreted_option_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +FileOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option) + return uninterpreted_option_; +} #endif // PROTOBUF_INLINE_NOT_IN_HEADERS @@ -9568,28 +9568,28 @@ int MessageOptions::uninterpreted_option_size() const { void MessageOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } - const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* MessageOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option) return &uninterpreted_option_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +MessageOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option) + return uninterpreted_option_; +} #endif // PROTOBUF_INLINE_NOT_IN_HEADERS @@ -10298,28 +10298,28 @@ int FieldOptions::uninterpreted_option_size() const { void FieldOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } - const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* FieldOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option) return &uninterpreted_option_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +FieldOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option) + return uninterpreted_option_; +} #endif // PROTOBUF_INLINE_NOT_IN_HEADERS @@ -10721,28 +10721,28 @@ int EnumOptions::uninterpreted_option_size() const { void EnumOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } - const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* EnumOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option) return &uninterpreted_option_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +EnumOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option) + return uninterpreted_option_; +} #endif // PROTOBUF_INLINE_NOT_IN_HEADERS @@ -11070,28 +11070,28 @@ int EnumValueOptions::uninterpreted_option_size() const { void EnumValueOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } - const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* EnumValueOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option) return &uninterpreted_option_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +EnumValueOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option) + return uninterpreted_option_; +} #endif // PROTOBUF_INLINE_NOT_IN_HEADERS @@ -11419,28 +11419,28 @@ int ServiceOptions::uninterpreted_option_size() const { void ServiceOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } - const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* ServiceOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option) return &uninterpreted_option_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +ServiceOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option) + return uninterpreted_option_; +} #endif // PROTOBUF_INLINE_NOT_IN_HEADERS @@ -11768,28 +11768,28 @@ int MethodOptions::uninterpreted_option_size() const { void MethodOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } - const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* MethodOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option) return &uninterpreted_option_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +MethodOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option) + return uninterpreted_option_; +} #endif // PROTOBUF_INLINE_NOT_IN_HEADERS @@ -12710,28 +12710,28 @@ int UninterpretedOption::name_size() const { void UninterpretedOption::clear_name() { name_.Clear(); } - const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* UninterpretedOption::mutable_name() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name) return &name_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& +UninterpretedOption::name() const { + // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name) + return name_; +} // optional string identifier_value = 3; bool UninterpretedOption::has_identifier_value() const { @@ -13916,28 +13916,28 @@ int SourceCodeInfo::location_size() const { void SourceCodeInfo::clear_location() { location_.Clear(); } - const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const { +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) { +::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() { +::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 >* +::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* SourceCodeInfo::mutable_location() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location) return &location_; } +const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& +SourceCodeInfo::location() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location) + return location_; +} #endif // PROTOBUF_INLINE_NOT_IN_HEADERS diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index 2aa076ae..931ff02d 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -38,28 +38,28 @@ void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto( void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); -class FileDescriptorSet; -class FileDescriptorProto; class DescriptorProto; class DescriptorProto_ExtensionRange; class DescriptorProto_ReservedRange; -class FieldDescriptorProto; -class OneofDescriptorProto; class EnumDescriptorProto; +class EnumOptions; class EnumValueDescriptorProto; -class ServiceDescriptorProto; -class MethodDescriptorProto; +class EnumValueOptions; +class FieldDescriptorProto; +class FieldOptions; +class FileDescriptorProto; +class FileDescriptorSet; class FileOptions; class MessageOptions; -class FieldOptions; -class EnumOptions; -class EnumValueOptions; -class ServiceOptions; +class MethodDescriptorProto; class MethodOptions; -class UninterpretedOption; -class UninterpretedOption_NamePart; +class OneofDescriptorProto; +class ServiceDescriptorProto; +class ServiceOptions; class SourceCodeInfo; class SourceCodeInfo_Location; +class UninterpretedOption; +class UninterpretedOption_NamePart; enum FieldDescriptorProto_Type { FieldDescriptorProto_Type_TYPE_DOUBLE = 1, @@ -249,10 +249,10 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* mutable_file(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& + file() const; // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet) private: @@ -405,10 +405,10 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* mutable_message_type(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& + message_type() const; // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; int enum_type_size() const; @@ -417,10 +417,10 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* mutable_enum_type(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& + enum_type() const; // repeated .google.protobuf.ServiceDescriptorProto service = 6; int service_size() const; @@ -429,10 +429,10 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* mutable_service(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& + service() const; // repeated .google.protobuf.FieldDescriptorProto extension = 7; int extension_size() const; @@ -441,10 +441,10 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_extension(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& + extension() const; // optional .google.protobuf.FileOptions options = 8; bool has_options() const; @@ -797,10 +797,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_field(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& + field() const; // repeated .google.protobuf.FieldDescriptorProto extension = 6; int extension_size() const; @@ -809,10 +809,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_extension(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& + extension() const; // repeated .google.protobuf.DescriptorProto nested_type = 3; int nested_type_size() const; @@ -821,10 +821,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* mutable_nested_type(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& + nested_type() const; // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; int enum_type_size() const; @@ -833,10 +833,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* mutable_enum_type(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& + enum_type() const; // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; int extension_range_size() const; @@ -845,10 +845,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* mutable_extension_range(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >& + extension_range() const; // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; int oneof_decl_size() const; @@ -857,10 +857,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >* mutable_oneof_decl(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& + oneof_decl() const; // optional .google.protobuf.MessageOptions options = 7; bool has_options() const; @@ -878,10 +878,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { 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(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >& + reserved_range() const; // repeated string reserved_name = 10; int reserved_name_size() const; @@ -1361,10 +1361,10 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* mutable_value(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& + value() const; // optional .google.protobuf.EnumOptions options = 3; bool has_options() const; @@ -1596,10 +1596,10 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* mutable_method(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& + method() const; // optional .google.protobuf.ServiceOptions options = 3; bool has_options() const; @@ -2014,10 +2014,10 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + uninterpreted_option() const; GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions) // @@protoc_insertion_point(class_scope:google.protobuf.FileOptions) @@ -2182,10 +2182,10 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message { 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + uninterpreted_option() const; GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions) // @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions) @@ -2381,10 +2381,10 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + uninterpreted_option() const; GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions) // @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions) @@ -2508,10 +2508,10 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message { 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + uninterpreted_option() const; GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions) // @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions) @@ -2616,10 +2616,10 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message { 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + uninterpreted_option() const; GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions) // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions) @@ -2721,10 +2721,10 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message { 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + uninterpreted_option() const; GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions) // @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions) @@ -2826,10 +2826,10 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message { 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + uninterpreted_option() const; GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions) // @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions) @@ -3033,10 +3033,10 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* mutable_name(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& + name() const; // optional string identifier_value = 3; bool has_identifier_value() const; @@ -3356,10 +3356,10 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message { 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; ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* mutable_location(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& + location() const; // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo) private: @@ -3402,16 +3402,16 @@ inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() { // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file) return file_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& -FileDescriptorSet::file() const { - // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file) - return file_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* FileDescriptorSet::mutable_file() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file) return &file_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& +FileDescriptorSet::file() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file) + return file_; +} // ------------------------------------------------------------------- @@ -3656,16 +3656,16 @@ inline ::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_typ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type) return message_type_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& -FileDescriptorProto::message_type() const { - // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type) - return message_type_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* FileDescriptorProto::mutable_message_type() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type) return &message_type_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& +FileDescriptorProto::message_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type) + return message_type_; +} // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; inline int FileDescriptorProto::enum_type_size() const { @@ -3686,16 +3686,16 @@ inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_ty // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type) return enum_type_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& -FileDescriptorProto::enum_type() const { - // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type) - return enum_type_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* FileDescriptorProto::mutable_enum_type() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type) return &enum_type_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& +FileDescriptorProto::enum_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type) + return enum_type_; +} // repeated .google.protobuf.ServiceDescriptorProto service = 6; inline int FileDescriptorProto::service_size() const { @@ -3716,16 +3716,16 @@ inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_serv // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service) return service_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& -FileDescriptorProto::service() const { - // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service) - return service_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* FileDescriptorProto::mutable_service() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service) return &service_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& +FileDescriptorProto::service() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service) + return service_; +} // repeated .google.protobuf.FieldDescriptorProto extension = 7; inline int FileDescriptorProto::extension_size() const { @@ -3746,16 +3746,16 @@ inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extens // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension) return extension_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& -FileDescriptorProto::extension() const { - // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension) - return extension_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* FileDescriptorProto::mutable_extension() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension) return &extension_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +FileDescriptorProto::extension() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension) + return extension_; +} // optional .google.protobuf.FileOptions options = 8; inline bool FileDescriptorProto::has_options() const { @@ -4076,16 +4076,16 @@ inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() { // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field) return field_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& -DescriptorProto::field() const { - // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field) - return field_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* DescriptorProto::mutable_field() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field) return &field_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +DescriptorProto::field() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field) + return field_; +} // repeated .google.protobuf.FieldDescriptorProto extension = 6; inline int DescriptorProto::extension_size() const { @@ -4106,16 +4106,16 @@ inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension( // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension) return extension_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& -DescriptorProto::extension() const { - // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension) - return extension_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* DescriptorProto::mutable_extension() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension) return &extension_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +DescriptorProto::extension() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension) + return extension_; +} // repeated .google.protobuf.DescriptorProto nested_type = 3; inline int DescriptorProto::nested_type_size() const { @@ -4136,16 +4136,16 @@ inline ::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() { // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type) return nested_type_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& -DescriptorProto::nested_type() const { - // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type) - return nested_type_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* DescriptorProto::mutable_nested_type() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type) return &nested_type_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& +DescriptorProto::nested_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type) + return nested_type_; +} // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; inline int DescriptorProto::enum_type_size() const { @@ -4166,16 +4166,16 @@ inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type) return enum_type_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& -DescriptorProto::enum_type() const { - // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type) - return enum_type_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* DescriptorProto::mutable_enum_type() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type) return &enum_type_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& +DescriptorProto::enum_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type) + return enum_type_; +} // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; inline int DescriptorProto::extension_range_size() const { @@ -4196,16 +4196,16 @@ inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range) return extension_range_.Add(); } -inline 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_; -} inline ::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_; } +inline 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_; +} // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; inline int DescriptorProto::oneof_decl_size() const { @@ -4226,16 +4226,16 @@ inline ::google::protobuf::OneofDescriptorProto* DescriptorProto::add_oneof_decl // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl) return oneof_decl_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& -DescriptorProto::oneof_decl() const { - // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl) - return oneof_decl_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >* DescriptorProto::mutable_oneof_decl() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl) return &oneof_decl_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& +DescriptorProto::oneof_decl() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_; +} // optional .google.protobuf.MessageOptions options = 7; inline bool DescriptorProto::has_options() const { @@ -4299,16 +4299,16 @@ inline ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_r // @@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_; } +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_; +} // repeated string reserved_name = 10; inline int DescriptorProto::reserved_name_size() const { @@ -4854,16 +4854,16 @@ inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_va // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value) return value_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& -EnumDescriptorProto::value() const { - // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value) - return value_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* EnumDescriptorProto::mutable_value() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value) return &value_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& +EnumDescriptorProto::value() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value) + return value_; +} // optional .google.protobuf.EnumOptions options = 3; inline bool EnumDescriptorProto::has_options() const { @@ -5108,16 +5108,16 @@ inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_me // @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method) return method_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& -ServiceDescriptorProto::method() const { - // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method) - return method_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* ServiceDescriptorProto::mutable_method() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method) return &method_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& +ServiceDescriptorProto::method() const { + // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method) + return method_; +} // optional .google.protobuf.ServiceOptions options = 3; inline bool ServiceDescriptorProto::has_options() const { @@ -5945,16 +5945,16 @@ inline ::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_o // @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option) return uninterpreted_option_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& -FileOptions::uninterpreted_option() const { - // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option) - return uninterpreted_option_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* FileOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option) return &uninterpreted_option_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +FileOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option) + return uninterpreted_option_; +} // ------------------------------------------------------------------- @@ -6075,16 +6075,16 @@ inline ::google::protobuf::UninterpretedOption* MessageOptions::add_uninterprete // @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option) return uninterpreted_option_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& -MessageOptions::uninterpreted_option() const { - // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option) - return uninterpreted_option_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* MessageOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option) return &uninterpreted_option_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +MessageOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option) + return uninterpreted_option_; +} // ------------------------------------------------------------------- @@ -6255,16 +6255,16 @@ inline ::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_ // @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option) return uninterpreted_option_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& -FieldOptions::uninterpreted_option() const { - // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option) - return uninterpreted_option_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* FieldOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option) return &uninterpreted_option_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +FieldOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option) + return uninterpreted_option_; +} // ------------------------------------------------------------------- @@ -6337,16 +6337,16 @@ inline ::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_o // @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option) return uninterpreted_option_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& -EnumOptions::uninterpreted_option() const { - // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option) - return uninterpreted_option_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* EnumOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option) return &uninterpreted_option_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +EnumOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option) + return uninterpreted_option_; +} // ------------------------------------------------------------------- @@ -6395,16 +6395,16 @@ inline ::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpre // @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option) return uninterpreted_option_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& -EnumValueOptions::uninterpreted_option() const { - // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option) - return uninterpreted_option_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* EnumValueOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option) return &uninterpreted_option_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +EnumValueOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option) + return uninterpreted_option_; +} // ------------------------------------------------------------------- @@ -6453,16 +6453,16 @@ inline ::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterprete // @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option) return uninterpreted_option_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& -ServiceOptions::uninterpreted_option() const { - // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option) - return uninterpreted_option_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* ServiceOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option) return &uninterpreted_option_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +ServiceOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option) + return uninterpreted_option_; +} // ------------------------------------------------------------------- @@ -6511,16 +6511,16 @@ inline ::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted // @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option) return uninterpreted_option_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& -MethodOptions::uninterpreted_option() const { - // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option) - return uninterpreted_option_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* MethodOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option) return &uninterpreted_option_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +MethodOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option) + return uninterpreted_option_; +} // ------------------------------------------------------------------- @@ -6626,16 +6626,16 @@ inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::ad // @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name) return name_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& -UninterpretedOption::name() const { - // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name) - return name_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* UninterpretedOption::mutable_name() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name) return &name_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& +UninterpretedOption::name() const { + // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name) + return name_; +} // optional string identifier_value = 3; inline bool UninterpretedOption::has_identifier_value() const { @@ -7115,16 +7115,16 @@ inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location) return location_.Add(); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& -SourceCodeInfo::location() const { - // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location) - return location_; -} inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* SourceCodeInfo::mutable_location() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location) return &location_; } +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& +SourceCodeInfo::location() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location) + return location_; +} #endif // !PROTOBUF_INLINE_NOT_IN_HEADERS // ------------------------------------------------------------------- diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index 9d3dd8fb..8f90a956 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -42,9 +42,9 @@ 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"; +// Re-enable this once the tools have picked up the csharp_namespace option. +// option csharp_namespace = "Google.ProtocolBuffers.DescriptorProtos"; option objc_class_prefix = "GPB"; // descriptor.proto must be optimized for speed because reflection-based @@ -301,10 +301,12 @@ message FileOptions { // If set true, then the Java code generator will generate equals() and // hashCode() methods for all messages defined in the .proto file. - // - In the full runtime, this is purely a speed optimization, as the + // This increases generated code size, potentially substantially for large + // protos, which may harm a memory-constrained application. + // - In the full runtime this is a speed optimization, as the // AbstractMessage base class includes reflection-based implementations of // these methods. - //- In the lite runtime, setting this option changes the semantics of + // - In the lite runtime, setting this option changes the semantics of // equals() and hashCode() to more closely match those of the full runtime; // the generated methods compute their results based on field values rather // than object identity. (Implementations should not assume that hashcodes @@ -525,6 +527,7 @@ 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; diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc index 1c03c443..a87fa049 100644 --- a/src/google/protobuf/descriptor_database_unittest.cc +++ b/src/google/protobuf/descriptor_database_unittest.cc @@ -42,7 +42,9 @@ #include #include +#include #include +#include #include #include diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index 760df097..e9b027db 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -49,6 +49,8 @@ #include #include +#include +#include #include #include @@ -368,6 +370,37 @@ TEST_F(FileDescriptorTest, BuildAgain) { EXPECT_TRUE(pool_.BuildFile(file) == NULL); } +TEST_F(FileDescriptorTest, BuildAgainWithSyntax) { + // Test that if te call BuildFile again on the same input we get the same + // FileDescriptor back even if syntax param is specified. + FileDescriptorProto proto_syntax2; + proto_syntax2.set_name("foo_syntax2"); + proto_syntax2.set_syntax("proto2"); + + const FileDescriptor* proto2_descriptor = pool_.BuildFile(proto_syntax2); + EXPECT_TRUE(proto2_descriptor != NULL); + EXPECT_EQ(proto2_descriptor, pool_.BuildFile(proto_syntax2)); + + FileDescriptorProto implicit_proto2; + implicit_proto2.set_name("foo_implicit_syntax2"); + + const FileDescriptor* implicit_proto2_descriptor = + pool_.BuildFile(implicit_proto2); + EXPECT_TRUE(implicit_proto2_descriptor != NULL); + // We get the same FileDescriptor back if syntax param is explicitly + // specified. + implicit_proto2.set_syntax("proto2"); + EXPECT_EQ(implicit_proto2_descriptor, pool_.BuildFile(implicit_proto2)); + + FileDescriptorProto proto_syntax3; + proto_syntax3.set_name("foo_syntax3"); + proto_syntax3.set_syntax("proto3"); + + const FileDescriptor* proto3_descriptor = pool_.BuildFile(proto_syntax3); + EXPECT_TRUE(proto3_descriptor != NULL); + EXPECT_EQ(proto3_descriptor, pool_.BuildFile(proto_syntax3)); +} + TEST_F(FileDescriptorTest, Syntax) { FileDescriptorProto proto; proto.set_name("foo"); @@ -3583,7 +3616,7 @@ TEST_F(ValidationErrorTest, FieldOneofIndexNegative) { TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) { // Fields belonging to the same oneof must be defined consecutively. - BuildFileWithWarnings( + BuildFileWithErrors( "name: \"foo.proto\" " "message_type {" " name: \"Foo\"" @@ -3600,7 +3633,7 @@ TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) { "\"foos\" oneof definition.\n"); // Prevent interleaved fields, which belong to different oneofs. - BuildFileWithWarnings( + BuildFileWithErrors( "name: \"foo2.proto\" " "message_type {" " name: \"Foo2\"" @@ -3621,6 +3654,25 @@ TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) { "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"); + + // Another case for normal fields and different oneof fields interleave. + BuildFileWithErrors( + "name: \"foo3.proto\" " + "message_type {" + " name: \"Foo3\"" + " 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:\"baz\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " field { name:\"foo2\" number: 4 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: 0 }" + " oneof_decl { name:\"foos\" }" + " oneof_decl { name:\"bars\" }" + "}", + "foo3.proto: Foo3.baz: OTHER: Fields in the same oneof must be defined " + "consecutively. \"baz\" cannot be defined before the completion of the " + "\"foos\" oneof definition.\n"); } TEST_F(ValidationErrorTest, FieldNumberConflict) { @@ -5369,6 +5421,35 @@ TEST_F(ValidationErrorTest, MapEntryConflictsWithOneof) { "with an existing oneof type.\n"); } +TEST_F(ValidationErrorTest, MapEntryUsesNoneZeroEnumDefaultValue) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type {" + " name: \"Bar\"" + " value { name:\"ENUM_A\" number:1 }" + " value { name:\"ENUM_B\" number:2 }" + "}" + "message_type {" + " name: 'Foo' " + " field { " + " name: 'foo_map' number: 1 label:LABEL_REPEATED " + " type_name: 'FooMapEntry' " + " } " + " nested_type { " + " name: 'FooMapEntry' " + " options { map_entry: true } " + " field { " + " name: 'key' number: 1 type:TYPE_INT32 label:LABEL_OPTIONAL " + " } " + " field { " + " name: 'value' number: 2 type_name:\"Bar\" label:LABEL_OPTIONAL " + " } " + " } " + "}", + "foo.proto: Foo.foo_map: " + "TYPE: Enum value in map must define 0 as the first value.\n"); +} + TEST_F(ValidationErrorTest, Proto3RequiredFields) { BuildFileWithErrors( "name: 'foo.proto' " diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc index 318ce6f9..2324d952 100644 --- a/src/google/protobuf/dynamic_message.cc +++ b/src/google/protobuf/dynamic_message.cc @@ -65,6 +65,7 @@ #include #include +#include #include #include @@ -79,6 +80,7 @@ #include #include #include +#include namespace google { namespace protobuf { @@ -87,7 +89,7 @@ using internal::WireFormat; using internal::ExtensionSet; using internal::GeneratedMessageReflection; using internal::MapField; -using internal::MapFieldBase; +using internal::DynamicMapField; using internal::ArenaStringPtr; @@ -116,7 +118,7 @@ int FieldSpaceUsed(const FieldDescriptor* field) { case FD::CPPTYPE_ENUM : return sizeof(RepeatedField); case FD::CPPTYPE_MESSAGE: if (IsMapFieldInApi(field)) { - return sizeof(MapFieldBase); + return sizeof(DynamicMapField); } else { return sizeof(RepeatedPtrField); } @@ -389,7 +391,8 @@ void DynamicMessage::SharedCtor() { new(field_ptr) Message*(NULL); } else { if (IsMapFieldInApi(field)) { - new (field_ptr) MapFieldBase(); + new (field_ptr) DynamicMapField( + type_info_->factory->GetPrototypeNoLock(field->message_type())); } else { new (field_ptr) RepeatedPtrField(); } @@ -437,8 +440,8 @@ DynamicMessage::~DynamicMessage() { &(reinterpret_cast( type_info_->prototype->OffsetToPointer( type_info_->offsets[i]))->Get(NULL)); - reinterpret_cast(field_ptr)->Destroy(default_value, - NULL); + reinterpret_cast(field_ptr)->Destroy( + default_value, NULL); break; } } @@ -480,7 +483,7 @@ DynamicMessage::~DynamicMessage() { case FieldDescriptor::CPPTYPE_MESSAGE: if (IsMapFieldInApi(field)) { - reinterpret_cast(field_ptr)->~MapFieldBase(); + reinterpret_cast(field_ptr)->~DynamicMapField(); } else { reinterpret_cast*>(field_ptr) ->~RepeatedPtrField(); @@ -496,8 +499,8 @@ DynamicMessage::~DynamicMessage() { &(reinterpret_cast( type_info_->prototype->OffsetToPointer( type_info_->offsets[i]))->Get(NULL)); - reinterpret_cast(field_ptr)->Destroy(default_value, - NULL); + reinterpret_cast(field_ptr)->Destroy( + default_value, NULL); break; } } @@ -723,8 +726,14 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( // Allocate the prototype. void* base = operator new(size); memset(base, 0, size); + // The prototype in type_info has to be set before creating the prototype + // instance on memory. e.g., message Foo { map a = 1; }. When + // creating prototype for Foo, prototype of the map entry will also be + // created, which needs the address of the prototype of Foo (the value in + // map). To break the cyclic dependency, we have to assgin the address of + // prototype into type_info first. + type_info->prototype = static_cast(base); DynamicMessage* prototype = new(base) DynamicMessage(type_info); - type_info->prototype = prototype; // Construct the reflection object. if (type->oneof_decl_count() > 0) { diff --git a/src/google/protobuf/dynamic_message.h b/src/google/protobuf/dynamic_message.h index b5928a52..f74cd7dd 100644 --- a/src/google/protobuf/dynamic_message.h +++ b/src/google/protobuf/dynamic_message.h @@ -45,6 +45,7 @@ #include #include +#include namespace google { namespace protobuf { diff --git a/src/google/protobuf/dynamic_message_unittest.cc b/src/google/protobuf/dynamic_message_unittest.cc index 522a092a..b9796c76 100644 --- a/src/google/protobuf/dynamic_message_unittest.cc +++ b/src/google/protobuf/dynamic_message_unittest.cc @@ -40,6 +40,7 @@ // reflection_ops_unittest, cover the rest of the functionality used by // DynamicMessage. +#include #include #include #include @@ -48,6 +49,7 @@ #include #include +#include #include #include diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h index c371e011..9ef4e27d 100644 --- a/src/google/protobuf/extension_set.h +++ b/src/google/protobuf/extension_set.h @@ -45,6 +45,7 @@ #include +#include #include @@ -330,6 +331,8 @@ class LIBPROTOBUF_EXPORT ExtensionSet { const MessageLite& prototype, desc); MessageLite* AddMessage(const FieldDescriptor* descriptor, MessageFactory* factory); + void AddAllocatedMessage(const FieldDescriptor* descriptor, + MessageLite* new_entry); #undef desc void RemoveLast(int number); @@ -578,6 +581,10 @@ class LIBPROTOBUF_EXPORT ExtensionSet { bool MaybeNewExtension(int number, const FieldDescriptor* descriptor, Extension** result); + // Gets the repeated extension for the given descriptor, creating it if + // it does not exist. + Extension* MaybeNewRepeatedExtension(const FieldDescriptor* descriptor); + // Parse a single MessageSet item -- called just after the item group start // tag has been read. bool ParseMessageSetItem(io::CodedInputStream* input, diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc index 330bd828..82e3e099 100644 --- a/src/google/protobuf/extension_set_heavy.cc +++ b/src/google/protobuf/extension_set_heavy.cc @@ -213,8 +213,7 @@ MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor, } } -MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor, - MessageFactory* factory) { +ExtensionSet::Extension* ExtensionSet::MaybeNewRepeatedExtension(const FieldDescriptor* descriptor) { Extension* extension; if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) { extension->type = descriptor->type(); @@ -225,6 +224,12 @@ MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor, } else { GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE); } + return extension; +} + +MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor, + MessageFactory* factory) { + Extension* extension = MaybeNewRepeatedExtension(descriptor); // RepeatedPtrField does not know how to Add() since it cannot // allocate an abstract object, so we have to be tricky. @@ -244,6 +249,13 @@ MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor, return result; } +void ExtensionSet::AddAllocatedMessage(const FieldDescriptor* descriptor, + MessageLite* new_entry) { + Extension* extension = MaybeNewRepeatedExtension(descriptor); + + extension->repeated_message_value->AddAllocated(new_entry); +} + static bool ValidateEnumUsingDescriptor(const void* arg, int number) { return reinterpret_cast(arg) ->FindValueByNumber(number) != NULL; diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc index 684ce002..1569120d 100644 --- a/src/google/protobuf/extension_set_unittest.cc +++ b/src/google/protobuf/extension_set_unittest.cc @@ -44,6 +44,7 @@ #include #include +#include #include #include #include @@ -173,7 +174,7 @@ TEST(ExtensionSetTest, SetAllocatedExtension) { } TEST(ExtensionSetTest, ReleaseExtension) { - unittest::TestMessageSet message; + proto2_wireformat_unittest::TestMessageSet message; EXPECT_FALSE(message.HasExtension( unittest::TestMessageSetExtension1::message_set_extension)); // Add a extension using SetAllocatedExtension diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index 412c48a1..b9957e75 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -818,7 +819,16 @@ void GeneratedMessageReflection::ClearField( } case FieldDescriptor::CPPTYPE_MESSAGE: - (*MutableRaw(message, field))->Clear(); + if (has_bits_offset_ == -1) { + // Proto3 does not have has-bits and we need to set a message field + // to NULL in order to indicate its un-presence. + if (GetArena(message) == NULL) { + delete *MutableRaw(message, field); + } + *MutableRaw(message, field) = NULL; + } else { + (*MutableRaw(message, field))->Clear(); + } break; } } @@ -1649,6 +1659,25 @@ Message* GeneratedMessageReflection::AddMessage( } } +void GeneratedMessageReflection::AddAllocatedMessage( + Message* message, const FieldDescriptor* field, + Message* new_entry) const { + USAGE_CHECK_ALL(AddAllocatedMessage, REPEATED, MESSAGE); + + if (field->is_extension()) { + MutableExtensionSet(message)->AddAllocatedMessage(field, new_entry); + } else { + RepeatedPtrFieldBase* repeated = NULL; + if (IsMapFieldInApi(field)) { + repeated = + MutableRaw(message, field)->MutableRepeatedField(); + } else { + repeated = MutableRaw(message, field); + } + repeated->AddAllocated >(new_entry); + } +} + void* GeneratedMessageReflection::MutableRawRepeatedField( Message* message, const FieldDescriptor* field, FieldDescriptor::CppType cpptype, @@ -1675,6 +1704,37 @@ void* GeneratedMessageReflection::MutableRawRepeatedField( } } +const void* GeneratedMessageReflection::GetRawRepeatedField( + const Message& message, const FieldDescriptor* field, + FieldDescriptor::CppType cpptype, + int ctype, const Descriptor* desc) const { + USAGE_CHECK_REPEATED("GetRawRepeatedField"); + if (field->cpp_type() != cpptype) + ReportReflectionUsageTypeError(descriptor_, + field, "GetRawRepeatedField", cpptype); + if (ctype >= 0) + GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch"; + if (desc != NULL) + GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type"; + if (field->is_extension()) { + // Should use extension_set::GetRawRepeatedField. However, the required + // parameter "default repeated value" is not very easy to get here. + // Map is not supported in extensions, it is acceptable to use + // extension_set::MutableRawRepeatedField which does not change the message. + return MutableExtensionSet(const_cast(&message)) + ->MutableRawRepeatedField( + field->number(), field->type(), field->is_packed(), field); + } else { + // Trigger transform for MapField + if (IsMapFieldInApi(field)) { + return &(reinterpret_cast( + reinterpret_cast(&message) + + offsets_[field->index()])->GetRepeatedField()); + } + return reinterpret_cast(&message) + offsets_[field->index()]; + } +} + const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor( const Message& message, const OneofDescriptor* oneof_descriptor) const { @@ -1685,6 +1745,69 @@ const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor( return descriptor_->FindFieldByNumber(field_number); } +bool GeneratedMessageReflection::ContainsMapKey( + const Message& message, + const FieldDescriptor* field, + const MapKey& key) const { + USAGE_CHECK(IsMapFieldInApi(field), + "LookupMapValue", + "Field is not a map field."); + return GetRaw(message, field).ContainsMapKey(key); +} + +bool GeneratedMessageReflection::InsertOrLookupMapValue( + Message* message, + const FieldDescriptor* field, + const MapKey& key, + MapValueRef* val) const { + USAGE_CHECK(IsMapFieldInApi(field), + "InsertOrLookupMapValue", + "Field is not a map field."); + val->SetType(field->message_type()->FindFieldByName("value")->cpp_type()); + return MutableRaw(message, field)->InsertMapValue(key, val); +} + +bool GeneratedMessageReflection::DeleteMapValue( + Message* message, + const FieldDescriptor* field, + const MapKey& key) const { + USAGE_CHECK(IsMapFieldInApi(field), + "DeleteMapValue", + "Field is not a map field."); + return MutableRaw(message, field)->DeleteMapValue(key); +} + +MapIterator GeneratedMessageReflection::MapBegin( + Message* message, + const FieldDescriptor* field) const { + USAGE_CHECK(IsMapFieldInApi(field), + "MapBegin", + "Field is not a map field."); + MapIterator iter(message, field); + GetRaw(*message, field).MapBegin(&iter); + return iter; +} + +MapIterator GeneratedMessageReflection::MapEnd( + Message* message, + const FieldDescriptor* field) const { + USAGE_CHECK(IsMapFieldInApi(field), + "MapEnd", + "Field is not a map field."); + MapIterator iter(message, field); + GetRaw(*message, field).MapEnd(&iter); + return iter; +} + +int GeneratedMessageReflection::MapSize( + const Message& message, + const FieldDescriptor* field) const { + USAGE_CHECK(IsMapFieldInApi(field), + "MapSize", + "Field is not a map field."); + return GetRaw(message, field).size(); +} + // ----------------------------------------------------------------------------- const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName( @@ -2098,6 +2221,14 @@ void* GeneratedMessageReflection::RepeatedFieldData( } } +MapFieldBase* GeneratedMessageReflection::MapData( + Message* message, const FieldDescriptor* field) const { + USAGE_CHECK(IsMapFieldInApi(field), + "GetMapData", + "Field is not a map field."); + return MutableRaw(message, field); +} + GeneratedMessageReflection* GeneratedMessageReflection::NewGeneratedMessageReflection( const Descriptor* descriptor, diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h index dc8abb98..85ce6e2e 100644 --- a/src/google/protobuf/generated_message_reflection.h +++ b/src/google/protobuf/generated_message_reflection.h @@ -58,7 +58,9 @@ class GMR_Handlers; } // namespace upb namespace protobuf { - class DescriptorPool; +class DescriptorPool; +class MapKey; +class MapValueRef; } namespace protobuf { @@ -261,6 +263,25 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { const Message& message, const OneofDescriptor* oneof_descriptor) const; + private: + bool ContainsMapKey(const Message& message, + const FieldDescriptor* field, + const MapKey& key) const; + bool InsertOrLookupMapValue(Message* message, + const FieldDescriptor* field, + const MapKey& key, + MapValueRef* val) const; + bool DeleteMapValue(Message* message, + const FieldDescriptor* field, + const MapKey& key) const; + MapIterator MapBegin( + Message* message, + const FieldDescriptor* field) const; + MapIterator MapEnd( + Message* message, + const FieldDescriptor* field) const; + int MapSize(const Message& message, const FieldDescriptor* field) const; + public: void SetInt32 (Message* message, const FieldDescriptor* field, int32 value) const; @@ -371,6 +392,9 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { int value) const; Message* AddMessage(Message* message, const FieldDescriptor* field, MessageFactory* factory = NULL) const; + void AddAllocatedMessage( + Message* message, const FieldDescriptor* field, + Message* new_entry) const; const FieldDescriptor* FindKnownExtensionByName(const string& name) const; const FieldDescriptor* FindKnownExtensionByNumber(int number) const; @@ -391,9 +415,14 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { static const int kUnknownFieldSetInMetadata = -1; protected: - virtual void* MutableRawRepeatedField( + void* MutableRawRepeatedField( Message* message, const FieldDescriptor* field, FieldDescriptor::CppType, - int ctype, const Descriptor* desc) const; + int ctype, const Descriptor* desc) const override; + + const void* GetRawRepeatedField( + const Message& message, const FieldDescriptor* field, + FieldDescriptor::CppType, int ctype, + const Descriptor* desc) const override; virtual MessageFactory* GetMessageFactory() const; @@ -407,7 +436,7 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { // To parse directly into a proto2 generated class, the class GMR_Handlers // needs access to member offsets and hasbits. - friend class LIBPROTOBUF_EXPORT upb::google_opensource::GMR_Handlers; + friend class upb::google_opensource::GMR_Handlers; const Descriptor* descriptor_; const Message* default_instance_; @@ -539,6 +568,9 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { Message* sub_message, const FieldDescriptor* field) const; + internal::MapFieldBase* MapData( + Message* message, const FieldDescriptor* field) const; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratedMessageReflection); }; diff --git a/src/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc index ca1a2918..df043844 100644 --- a/src/google/protobuf/generated_message_reflection_unittest.cc +++ b/src/google/protobuf/generated_message_reflection_unittest.cc @@ -47,6 +47,7 @@ #include #include +#include #include #include #include @@ -546,6 +547,57 @@ TEST(GeneratedMessageReflectionTest, SetAllocatedExtensionMessageTest) { &to_message, TestUtil::ReflectionTester::IS_NULL); } +TEST(GeneratedMessageReflectionTest, AddRepeatedMessage) { + unittest::TestAllTypes message; + + const Reflection* reflection = message.GetReflection(); + const Reflection* nested_reflection = + unittest::TestAllTypes::NestedMessage::default_instance().GetReflection(); + + const FieldDescriptor* nested_bb = + unittest::TestAllTypes::NestedMessage::descriptor()->FindFieldByName( + "bb"); + + Message* nested = reflection->AddMessage( + &message, F("repeated_nested_message")); + nested_reflection->SetInt32(nested, nested_bb, 11); + + EXPECT_EQ(11, message.repeated_nested_message(0).bb()); +} + +TEST(GeneratedMessageReflectionTest, MutableRepeatedMessage) { + unittest::TestAllTypes message; + + const Reflection* reflection = message.GetReflection(); + const Reflection* nested_reflection = + unittest::TestAllTypes::NestedMessage::default_instance().GetReflection(); + + const FieldDescriptor* nested_bb = + unittest::TestAllTypes::NestedMessage::descriptor()->FindFieldByName( + "bb"); + + message.add_repeated_nested_message()->set_bb(12); + + Message* nested = reflection->MutableRepeatedMessage( + &message, F("repeated_nested_message"), 0); + EXPECT_EQ(12, nested_reflection->GetInt32(*nested, nested_bb)); + nested_reflection->SetInt32(nested, nested_bb, 13); + EXPECT_EQ(13, message.repeated_nested_message(0).bb()); +} + +TEST(GeneratedMessageReflectionTest, AddAllocatedMessage) { + unittest::TestAllTypes message; + + const Reflection* reflection = message.GetReflection(); + + unittest::TestAllTypes::NestedMessage* nested = + new unittest::TestAllTypes::NestedMessage(); + nested->set_bb(11); + reflection->AddAllocatedMessage(&message, F("repeated_nested_message"), nested); + EXPECT_EQ(1, message.repeated_nested_message_size()); + EXPECT_EQ(11, message.repeated_nested_message(0).bb()); +} + TEST(GeneratedMessageReflectionTest, ListFieldsOneOf) { unittest::TestOneof2 message; TestUtil::SetOneof1(&message); diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc index 3b8650d6..4bcd354f 100644 --- a/src/google/protobuf/io/coded_stream.cc +++ b/src/google/protobuf/io/coded_stream.cc @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -338,9 +339,9 @@ namespace { // 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 ReadVarint32FromArray( +GOOGLE_ATTRIBUTE_ALWAYS_INLINE ::std::pair ReadVarint32FromArray( uint32 first_byte, const uint8* buffer, - uint32* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + uint32* value); inline ::std::pair ReadVarint32FromArray( uint32 first_byte, const uint8* buffer, uint32* value) { // Fast path: We have enough bytes left in the buffer to guarantee that diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h index ad351dc3..361c406b 100644 --- a/src/google/protobuf/io/coded_stream.h +++ b/src/google/protobuf/io/coded_stream.h @@ -191,16 +191,15 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Like GetDirectBufferPointer, but this method is inlined, and does not // attempt to Refresh() if the buffer is currently empty. - inline void GetDirectBufferPointerInline(const void** data, - int* size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + GOOGLE_ATTRIBUTE_ALWAYS_INLINE void GetDirectBufferPointerInline(const void** data, + int* size); // 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; + GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InternalReadRawInline(void* buffer, int size); // Like ReadRaw, but reads into a string. // @@ -212,8 +211,8 @@ class LIBPROTOBUF_EXPORT CodedInputStream { bool ReadString(string* buffer, int size); // Like the above, with inlined optimizations. This should only be used // by the protobuf implementation. - inline bool InternalReadStringInline(string* buffer, - int size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InternalReadStringInline(string* buffer, + int size); // Read a 32-bit little-endian integer. @@ -243,7 +242,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Always inline because this is only called in one place per parse loop // but it is called for every iteration of said loop, so it should be fast. // GCC doesn't want to inline this by default. - uint32 ReadTag() GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + GOOGLE_ATTRIBUTE_ALWAYS_INLINE uint32 ReadTag(); // This usually a faster alternative to ReadTag() when cutoff is a manifest // constant. It does particularly well for cutoff >= 127. The first part @@ -253,8 +252,8 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // above cutoff or is 0. (There's intentional wiggle room when tag is 0, // because that can arise in several ways, and for best performance we want // to avoid an extra "is tag == 0?" check here.) - inline std::pair ReadTagWithCutoff(uint32 cutoff) - GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + GOOGLE_ATTRIBUTE_ALWAYS_INLINE std::pair ReadTagWithCutoff( + uint32 cutoff); // Usually returns true if calling ReadVarint32() now would produce the given // value. Will always return false if ReadVarint32() would not return the @@ -263,7 +262,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // parameter. // Always inline because this collapses to a small number of instructions // when given a constant parameter, but GCC doesn't want to inline by default. - bool ExpectTag(uint32 expected) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool ExpectTag(uint32 expected); // Like above, except this reads from the specified buffer. The caller is // responsible for ensuring that the buffer is large enough to read a varint @@ -272,9 +271,9 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // // Returns a pointer beyond the expected tag if it was found, or NULL if it // was not. - static const uint8* ExpectTagFromArray( + GOOGLE_ATTRIBUTE_ALWAYS_INLINE static const uint8* ExpectTagFromArray( const uint8* buffer, - uint32 expected) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + uint32 expected); // Usually returns true if no more bytes can be read. Always returns false // if more bytes can be read. If ExpectAtEnd() returns true, a subsequent @@ -766,8 +765,8 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // but GCC by default doesn't want to inline this. void WriteTag(uint32 value); // Like WriteTag() but writing directly to the target array. - static uint8* WriteTagToArray( - uint32 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + GOOGLE_ATTRIBUTE_ALWAYS_INLINE static uint8* WriteTagToArray(uint32 value, + uint8* target); // Returns the number of bytes needed to encode the given value as a varint. static int VarintSize32(uint32 value); @@ -831,8 +830,8 @@ 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* WriteVarint64ToArrayInline( - uint64 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + GOOGLE_ATTRIBUTE_ALWAYS_INLINE static uint8* WriteVarint64ToArrayInline( + uint64 value, uint8* target); static int VarintSize32Fallback(uint32 value); }; diff --git a/src/google/protobuf/io/coded_stream_inl.h b/src/google/protobuf/io/coded_stream_inl.h index fa20f208..d95b06e0 100644 --- a/src/google/protobuf/io/coded_stream_inl.h +++ b/src/google/protobuf/io/coded_stream_inl.h @@ -36,6 +36,7 @@ #ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__ #define GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__ +#include #include #include #include diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc index 02d5bad3..630c9086 100644 --- a/src/google/protobuf/io/coded_stream_unittest.cc +++ b/src/google/protobuf/io/coded_stream_unittest.cc @@ -41,6 +41,8 @@ #include #include +#include +#include #include #include #include diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc index dd7c036e..1be6c863 100644 --- a/src/google/protobuf/io/gzip_stream.cc +++ b/src/google/protobuf/io/gzip_stream.cc @@ -33,10 +33,12 @@ // This file contains the implementation of classes GzipInputStream and // GzipOutputStream. + #if HAVE_ZLIB #include #include +#include namespace google { namespace protobuf { diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc index 3ae8c268..7d886506 100644 --- a/src/google/protobuf/io/printer.cc +++ b/src/google/protobuf/io/printer.cc @@ -34,6 +34,7 @@ #include #include +#include #include namespace google { diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc index 1331a8d9..258dd986 100644 --- a/src/google/protobuf/io/printer_unittest.cc +++ b/src/google/protobuf/io/printer_unittest.cc @@ -37,6 +37,7 @@ #include #include +#include #include #include #include diff --git a/src/google/protobuf/io/strtod.cc b/src/google/protobuf/io/strtod.cc index 56973439..579de9aa 100644 --- a/src/google/protobuf/io/strtod.cc +++ b/src/google/protobuf/io/strtod.cc @@ -34,6 +34,7 @@ #include #include +#include #include namespace google { diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc index 60bd7957..7ccd633d 100644 --- a/src/google/protobuf/io/tokenizer.cc +++ b/src/google/protobuf/io/tokenizer.cc @@ -90,6 +90,7 @@ #include #include +#include #include #include #include diff --git a/src/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h index 98576f56..49885eda 100644 --- a/src/google/protobuf/io/tokenizer.h +++ b/src/google/protobuf/io/tokenizer.h @@ -40,6 +40,7 @@ #include #include #include +#include namespace google { namespace protobuf { diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc index de096fb9..6526056a 100644 --- a/src/google/protobuf/io/tokenizer_unittest.cc +++ b/src/google/protobuf/io/tokenizer_unittest.cc @@ -41,6 +41,7 @@ #include #include +#include #include #include #include diff --git a/src/google/protobuf/io/zero_copy_stream.cc b/src/google/protobuf/io/zero_copy_stream.cc index f77c768f..186de001 100644 --- a/src/google/protobuf/io/zero_copy_stream.cc +++ b/src/google/protobuf/io/zero_copy_stream.cc @@ -34,6 +34,7 @@ #include +#include #include namespace google { diff --git a/src/google/protobuf/io/zero_copy_stream_impl.cc b/src/google/protobuf/io/zero_copy_stream_impl.cc index f7901b27..7ec2b5da 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl.cc +++ b/src/google/protobuf/io/zero_copy_stream_impl.cc @@ -46,6 +46,7 @@ #include #include +#include #include diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc index 97b73b88..686e63f2 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc @@ -39,6 +39,7 @@ #include #include +#include #include namespace google { 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 4360b18f..9cdf0378 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h @@ -48,6 +48,7 @@ #include #include #include +#include #include diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc index f2e5b629..3850e76c 100644 --- a/src/google/protobuf/io/zero_copy_stream_unittest.cc +++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc @@ -46,6 +46,7 @@ // "parametized tests" so that one set of tests can be used on all the // implementations. + #ifdef _MSC_VER #include #else @@ -66,6 +67,8 @@ #endif #include +#include +#include #include #include #include diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc index 5af8b24d..d1948ab5 100644 --- a/src/google/protobuf/lite_unittest.cc +++ b/src/google/protobuf/lite_unittest.cc @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -376,13 +377,6 @@ int main(int argc, char* argv[]) { 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; @@ -692,37 +686,6 @@ int main(int argc, char* argv[]) { EXPECT_TRUE(map_message.IsInitialized()); } - // arena support for map ========================================= - - { - // ParsingAndSerializingNoHeapAllocation - - // Allocate a large initial block to avoid mallocs during hooked test. - std::vector 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( - &arena); - google::protobuf::MapLiteTestUtil::SetArenaMapFields(from); - from->SerializeToString(&data); - - protobuf_unittest::TestArenaMapLite* to = - google::protobuf::Arena::CreateMessage( - &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 d928b7a7..c43df13e 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -35,9 +35,12 @@ #include #include // To support Visual Studio 2008 +#include #include #include #include +#include +#include namespace google { namespace protobuf { @@ -47,13 +50,379 @@ class Map; template struct is_proto_enum; +class MapIterator; + namespace internal { template class MapFieldLite; -} + +template +class MapField; + +template +class TypeDefinedMapFieldBase; + +class DynamicMapField; + +class GeneratedMessageReflection; +} // namespace internal + +#define TYPE_CHECK(EXPECTEDTYPE, METHOD) \ + if (type() != EXPECTEDTYPE) { \ + GOOGLE_LOG(FATAL) \ + << "Protocol Buffer map usage error:\n" \ + << METHOD << " type does not match\n" \ + << " Expected : " \ + << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \ + << " Actual : " \ + << FieldDescriptor::CppTypeName(type()); \ + } + +// MapKey is an union type for representing any possible +// map key. +class LIBPROTOBUF_EXPORT MapKey { + public: + MapKey() : type_(0) { + } + MapKey(const MapKey& other) : type_(0) { + CopyFrom(other); + } + + ~MapKey() { + if (type_ == FieldDescriptor::CPPTYPE_STRING) { + delete val_.string_value_; + } + } + + FieldDescriptor::CppType type() const { + if (type_ == 0) { + GOOGLE_LOG(FATAL) + << "Protocol Buffer map usage error:\n" + << "MapKey::type MapKey is not initialized. " + << "Call set methods to initialize MapKey."; + } + return (FieldDescriptor::CppType)type_; + } + + void SetInt64Value(int64 value) { + SetType(FieldDescriptor::CPPTYPE_INT64); + val_.int64_value_ = value; + } + void SetUInt64Value(uint64 value) { + SetType(FieldDescriptor::CPPTYPE_UINT64); + val_.uint64_value_ = value; + } + void SetInt32Value(int32 value) { + SetType(FieldDescriptor::CPPTYPE_INT32); + val_.int32_value_ = value; + } + void SetUInt32Value(uint32 value) { + SetType(FieldDescriptor::CPPTYPE_UINT32); + val_.uint32_value_ = value; + } + void SetBoolValue(bool value) { + SetType(FieldDescriptor::CPPTYPE_BOOL); + val_.bool_value_ = value; + } + void SetStringValue(const string& val) { + SetType(FieldDescriptor::CPPTYPE_STRING); + *val_.string_value_ = val; + } + + int64 GetInt64Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, + "MapKey::GetInt64Value"); + return val_.int64_value_; + } + uint64 GetUInt64Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, + "MapKey::GetUInt64Value"); + return val_.uint64_value_; + } + int32 GetInt32Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, + "MapKey::GetInt32Value"); + return val_.int32_value_; + } + uint32 GetUInt32Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, + "MapKey::GetUInt32Value"); + return val_.uint32_value_; + } + int32 GetBoolValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, + "MapKey::GetBoolValue"); + return val_.bool_value_; + } + const string& GetStringValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, + "MapKey::GetStringValue"); + return *val_.string_value_; + } + + bool operator==(const MapKey& other) const { + if (type_ != other.type_) { + return false; + } + switch (type()) { + case FieldDescriptor::CPPTYPE_STRING: + return *val_.string_value_ == *other.val_.string_value_; + case FieldDescriptor::CPPTYPE_INT64: + return val_.int64_value_ == other.val_.int64_value_; + case FieldDescriptor::CPPTYPE_INT32: + return val_.int32_value_ == other.val_.int32_value_; + case FieldDescriptor::CPPTYPE_UINT64: + return val_.uint64_value_ == other.val_.uint64_value_; + case FieldDescriptor::CPPTYPE_UINT32: + return val_.uint32_value_ == other.val_.uint32_value_; + case FieldDescriptor::CPPTYPE_BOOL: + return val_.bool_value_ == other.val_.bool_value_; + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Can't get here."; + return false; + } + } + + void CopyFrom(const MapKey& other) { + SetType(other.type()); + switch (type_) { + case FieldDescriptor::CPPTYPE_STRING: + *val_.string_value_ = *other.val_.string_value_; + break; + case FieldDescriptor::CPPTYPE_INT64: + val_.int64_value_ = other.val_.int64_value_; + break; + case FieldDescriptor::CPPTYPE_INT32: + val_.int32_value_ = other.val_.int32_value_; + break; + case FieldDescriptor::CPPTYPE_UINT64: + val_.uint64_value_ = other.val_.uint64_value_; + break; + case FieldDescriptor::CPPTYPE_UINT32: + val_.uint32_value_ = other.val_.uint32_value_; + break; + case FieldDescriptor::CPPTYPE_BOOL: + val_.bool_value_ = other.val_.bool_value_; + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Can't get here."; + break; + } + } + + private: + template + friend class internal::TypeDefinedMapFieldBase; + friend class MapIterator; + friend class internal::DynamicMapField; + + union KeyValue { + KeyValue() {} + string* string_value_; + int64 int64_value_; + int32 int32_value_; + uint64 uint64_value_; + uint32 uint32_value_; + bool bool_value_; + } val_; + + void SetType(FieldDescriptor::CppType type) { + if (type_ == type) return; + if (type_ == FieldDescriptor::CPPTYPE_STRING) { + delete val_.string_value_; + } + type_ = type; + if (type_ == FieldDescriptor::CPPTYPE_STRING) { + val_.string_value_ = new string; + } + } + + // type_ is 0 or a valid FieldDescriptor::CppType. + int type_; +}; + +// MapValueRef points to a map value. +class LIBPROTOBUF_EXPORT MapValueRef { + public: + MapValueRef() : data_(NULL), type_(0) {} + + void SetInt64Value(int64 value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, + "MapValueRef::SetInt64Value"); + *reinterpret_cast(data_) = value; + } + void SetUInt64Value(uint64 value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, + "MapValueRef::SetUInt64Value"); + *reinterpret_cast(data_) = value; + } + void SetInt32Value(int32 value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, + "MapValueRef::SetInt32Value"); + *reinterpret_cast(data_) = value; + } + void SetUInt32Value(uint64 value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, + "MapValueRef::SetUInt32Value"); + *reinterpret_cast(data_) = value; + } + void SetBoolValue(bool value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, + "MapValueRef::SetBoolValue"); + *reinterpret_cast(data_) = value; + } + // TODO(jieluo) - Checks that enum is member. + void SetEnumValue(int value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, + "MapValueRef::SetEnumValue"); + *reinterpret_cast(data_) = value; + } + void SetStringValue(const string& value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, + "MapValueRef::SetStringValue"); + *reinterpret_cast(data_) = value; + } + void SetFloatValue(float value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, + "MapValueRef::SetFloatValue"); + *reinterpret_cast(data_) = value; + } + void SetDoubleValue(double value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE, + "MapValueRef::SetDoubleValue"); + *reinterpret_cast(data_) = value; + } + + int64 GetInt64Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, + "MapValueRef::GetInt64Value"); + return *reinterpret_cast(data_); + } + uint64 GetUInt64Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, + "MapValueRef::GetUInt64Value"); + return *reinterpret_cast(data_); + } + int32 GetInt32Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, + "MapValueRef::GetInt32Value"); + return *reinterpret_cast(data_); + } + uint32 GetUInt32Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, + "MapValueRef::GetUInt32Value"); + return *reinterpret_cast(data_); + } + bool GetBoolValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, + "MapValueRef::GetBoolValue"); + return *reinterpret_cast(data_); + } + int GetEnumValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, + "MapValueRef::GetEnumValue"); + return *reinterpret_cast(data_); + } + const string& GetStringValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, + "MapValueRef::GetStringValue"); + return *reinterpret_cast(data_); + } + float GetFloatValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, + "MapValueRef::GetFloatValue"); + return *reinterpret_cast(data_); + } + double GetDoubleValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE, + "MapValueRef::GetDoubleValue"); + return *reinterpret_cast(data_); + } + + const Message& GetMessageValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE, + "MapValueRef::GetMessageValue"); + return *reinterpret_cast(data_); + } + + Message* MutableMessageValue() { + TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE, + "MapValueRef::MutableMessageValue"); + return reinterpret_cast(data_); + } + + private: + template + friend class internal::MapField; + template + friend class internal::TypeDefinedMapFieldBase; + friend class MapIterator; + friend class internal::GeneratedMessageReflection; + friend class internal::DynamicMapField; + + void SetType(FieldDescriptor::CppType type) { + type_ = type; + } + + FieldDescriptor::CppType type() const { + if (type_ == 0 || data_ == NULL) { + GOOGLE_LOG(FATAL) + << "Protocol Buffer map usage error:\n" + << "MapValueRef::type MapValueRef is not initialized."; + } + return (FieldDescriptor::CppType)type_; + } + void SetValue(const void* val) { + data_ = const_cast(val); + } + void CopyFrom(const MapValueRef& other) { + type_ = other.type_; + data_ = other.data_; + } + // Only used in DynamicMapField + void DeleteData() { + switch (type_) { +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + delete reinterpret_cast(data_); \ + break; \ + } + HANDLE_TYPE(INT32, int32); + HANDLE_TYPE(INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(STRING, string); + HANDLE_TYPE(ENUM, int32); + HANDLE_TYPE(MESSAGE, Message); +#undef HANDLE_TYPE + } + } + // data_ point to a map value. MapValueRef does not + // own this value. + void* data_; + // type_ is 0 or a valid FieldDescriptor::CppType. + int type_; +}; + +#undef TYPE_CHECK // 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 @@ -82,7 +451,6 @@ class MapPair { T second; private: - typedef void DestructorSkippable_; friend class ::google::protobuf::Arena; friend class Map; }; @@ -92,9 +460,6 @@ class MapPair { // interface directly to visit or change map fields. template class Map { - typedef internal::MapCppTypeHandler KeyTypeHandler; - typedef internal::MapCppTypeHandler ValueTypeHandler; - public: typedef Key key_type; typedef T mapped_type; @@ -118,7 +483,9 @@ class Map { : arena_(arena), allocator_(arena_), elements_(0, hasher(), key_equal(), allocator_), - default_enum_value_(0) {} + default_enum_value_(0) { + arena_->OwnDestructor(&elements_); + } Map(const Map& other) : arena_(NULL), @@ -127,6 +494,14 @@ class Map { default_enum_value_(other.default_enum_value_) { insert(other.begin(), other.end()); } + template + explicit Map(const InputIt& first, const InputIt& last) + : arena_(NULL), + allocator_(arena_), + elements_(0, hasher(), key_equal(), allocator_), + default_enum_value_(0) { + insert(first, last); + } ~Map() { clear(); } @@ -172,7 +547,7 @@ class Map { !defined(GOOGLE_PROTOBUF_OS_NACL) && !defined(GOOGLE_PROTOBUF_OS_ANDROID) template void construct(NodeType* p, Args&&... args) { - new ((void*)p) NodeType(std::forward(args)...); + new (static_cast(p)) NodeType(std::forward(args)...); } template @@ -206,6 +581,7 @@ class Map { } private: + typedef void DestructorSkippable_; Arena* arena_; template @@ -216,7 +592,7 @@ class Map { typedef MapAllocator*> > Allocator; // Iterators - class const_iterator + class LIBPROTOBUF_EXPORT const_iterator : public std::iterator { typedef typename hash_map, equal_to, @@ -449,6 +825,35 @@ class Map { }; } // namespace protobuf - } // namespace google + +GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START +template<> +struct hash { + size_t + operator()(const google::protobuf::MapKey& map_key) const { + switch (map_key.type()) { + case google::protobuf::FieldDescriptor::CPPTYPE_STRING: + return hash()(map_key.GetStringValue()); + case google::protobuf::FieldDescriptor::CPPTYPE_INT64: + return hash< ::google::protobuf::int64>()(map_key.GetInt64Value()); + case google::protobuf::FieldDescriptor::CPPTYPE_INT32: + return hash< ::google::protobuf::int32>()(map_key.GetInt32Value()); + case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: + return hash< ::google::protobuf::uint64>()(map_key.GetUInt64Value()); + case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: + return hash< ::google::protobuf::uint32>()(map_key.GetUInt32Value()); + case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: + return hash()(map_key.GetBoolValue()); + case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: + case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: + case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: + case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Can't get here."; + return 0; + } + } +}; +GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END + #endif // GOOGLE_PROTOBUF_MAP_H__ diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h index e93d0348..987c4e29 100644 --- a/src/google/protobuf/map_entry.h +++ b/src/google/protobuf/map_entry.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -79,40 +80,46 @@ class LIBPROTOBUF_EXPORT MapEntryBase : public Message { // MapEntry is the returned google::protobuf::Message when calling AddMessage of // google::protobuf::Reflection. In order to let it work with generated message -// reflection, its internal layout is the same as generated message with the -// same fields. However, in order to decide the internal layout of key/value, we -// need to know both their cpp type in generated api and proto type. +// reflection, its in-memory type is the same as generated message with the same +// fields. However, in order to decide the in-memory type of key/value, we need +// to know both their cpp type in generated api and proto type. In +// implmentation, all in-memory types have related wire format functions to +// support except ArenaStringPtr. Therefore, we need to define another type with +// supporting wire format functions. Since this type is only used as return type +// of MapEntry accessors, it's named MapEntry accessor type. // -// cpp type | proto type | internal layout -// int32 TYPE_INT32 int32 -// int32 TYPE_FIXED32 int32 -// FooEnum TYPE_ENUM int -// FooMessage TYPE_MESSAGE FooMessage* +// cpp type: the type visible to users in public API. +// proto type: WireFormatLite::FieldType of the field. +// in-memory type: type of the data member used to stored this field. +// MapEntry accessor type: type used in MapEntry getters/mutators to access the +// field. // -// The internal layouts of primitive types can be inferred from its proto type, -// 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. +// cpp type | proto type | in-memory type | MapEntry accessor type +// int32 TYPE_INT32 int32 int32 +// int32 TYPE_FIXED32 int32 int32 +// string TYPE_STRING ArenaStringPtr string +// FooEnum TYPE_ENUM int int +// FooMessage TYPE_MESSAGE FooMessage* FooMessage +// +// The in-memory types of primitive types can be inferred from its proto type, +// while we need to explicitly specify the cpp type if proto type is +// TYPE_MESSAGE to infer the in-memory type. Moreover, default_enum_value is +// used to initialize enum field in proto2. template class MapEntry : public MapEntryBase { - // Handlers for key/value wire type. Provide utilities to parse/serialize - // key/value. - typedef MapWireFieldTypeHandler KeyWireHandler; - typedef MapWireFieldTypeHandler 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::type - KeyCppType; - typedef typename MapIf::type - ValCppType; + // Provide utilities to parse/serialize key/value. Provide utilities to + // manipulate internal stored type. + typedef MapTypeHandler KeyTypeHandler; + typedef MapTypeHandler ValueTypeHandler; + + // Enum type cannot be used for MapTypeHandler::Read. Define a type + // which will replace Enum with int. + typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType; + typedef typename ValueTypeHandler::MapEntryAccessorType + ValueMapEntryAccessorType; // Abbreviation for MapEntry typedef typename google::protobuf::internal::MapEntry< @@ -132,16 +139,16 @@ class MapEntry : public MapEntryBase { // accessors ====================================================== - virtual inline const KeyCppType& key() const { + virtual inline const KeyMapEntryAccessorType& key() const { return entry_lite_.key(); } - inline KeyCppType* mutable_key() { + inline KeyMapEntryAccessorType* mutable_key() { return entry_lite_.mutable_key(); } - virtual inline const ValCppType& value() const { + virtual inline const ValueMapEntryAccessorType& value() const { return entry_lite_.value(); } - inline ValCppType* mutable_value() { + inline ValueMapEntryAccessorType* mutable_value() { return entry_lite_.mutable_value(); } @@ -240,7 +247,9 @@ class MapEntry : public MapEntryBase { 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); + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(MapEntry), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _internal_metadata_)); entry->descriptor_ = descriptor; entry->reflection_ = reflection; entry->set_default_instance(entry); @@ -250,10 +259,13 @@ class MapEntry : public MapEntryBase { } private: - MapEntry() : default_instance_(NULL), entry_lite_() {} + MapEntry() + : _internal_metadata_(NULL), default_instance_(NULL), entry_lite_() {} explicit MapEntry(Arena* arena) - : default_instance_(NULL), entry_lite_(arena) {} + : _internal_metadata_(arena), + default_instance_(NULL), + entry_lite_(arena) {} inline Arena* GetArenaNoVirtual() const { return entry_lite_.GetArenaNoVirtual(); @@ -266,6 +278,7 @@ class MapEntry : public MapEntryBase { static int offsets_[2]; UnknownFieldSet _unknown_fields_; + InternalMetadataWithArena _internal_metadata_; MapEntry* default_instance_; EntryLiteType entry_lite_; diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h index 52746da5..0e6ee013 100644 --- a/src/google/protobuf/map_entry_lite.h +++ b/src/google/protobuf/map_entry_lite.h @@ -61,38 +61,21 @@ template class MapEntryLite : public MessageLite { - // Handlers for key/value wire type. Provide utilities to parse/serialize - // key/value. - typedef MapWireFieldTypeHandler KeyWireHandler; - typedef MapWireFieldTypeHandler 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::type - KeyCppType; - typedef typename MapIf::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 KeyCppHandler; - typedef MapCppTypeHandler ValueCppHandler; + // Provide utilities to parse/serialize key/value. Provide utilities to + // manipulate internal stored type. + typedef MapTypeHandler KeyTypeHandler; + typedef MapTypeHandler ValueTypeHandler; // 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::type - KeyBase; - typedef typename MapIf::type - ValueBase; + typedef typename KeyTypeHandler::TypeOnMemory KeyOnMemory; + typedef typename ValueTypeHandler::TypeOnMemory ValueOnMemory; + + // Enum type cannot be used for MapTypeHandler::Read. Define a type + // which will replace Enum with int. + typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType; + typedef typename ValueTypeHandler::MapEntryAccessorType + ValueMapEntryAccessorType; // Constants for field number. static const int kKeyFieldNumber = 1; @@ -100,38 +83,37 @@ class MapEntryLite : public MessageLite { // Constants for field tag. static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( - kKeyFieldNumber, KeyWireHandler::kWireType); + kKeyFieldNumber, KeyTypeHandler::kWireType); static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( - kValueFieldNumber, ValueWireHandler::kWireType); + kValueFieldNumber, ValueTypeHandler::kWireType); static const int kTagSize = 1; public: ~MapEntryLite() { if (this != default_instance_) { - KeyCppHandler::Delete(key_); - ValueCppHandler::Delete(value_); + if (GetArenaNoVirtual() != NULL) return; + KeyTypeHandler::DeleteNoArena(key_); + ValueTypeHandler::DeleteNoArena(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 KeyMapEntryAccessorType& key() const { + return KeyTypeHandler::GetExternalReference(key_); } - virtual inline const ValCppType& value() const { + virtual inline const ValueMapEntryAccessorType& value() const { GOOGLE_CHECK(default_instance_ != NULL); - return ValueCppHandler::DefaultIfNotInitialized(value_, + return ValueTypeHandler::DefaultIfNotInitialized(value_, default_instance_->value_); } - inline ValCppType* mutable_value() { + inline KeyMapEntryAccessorType* mutable_key() { + set_has_key(); + return KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual()); + } + inline ValueMapEntryAccessorType* mutable_value() { set_has_value(); - ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual()); - return ValueCppHandler::Pointer(value_); + return ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual()); } // implements MessageLite ========================================= @@ -159,13 +141,17 @@ class MapEntryLite : public MessageLite { tag = input->ReadTag(); switch (tag) { case kKeyTag: - if (!KeyWireHandler::Read(input, mutable_key())) return false; + if (!KeyTypeHandler::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; + if (!ValueTypeHandler::Read(input, mutable_value())) { + return false; + } set_has_value(); if (input->ExpectAtEnd()) return true; break; @@ -184,32 +170,35 @@ class MapEntryLite : public MessageLite { int ByteSize() const { int size = 0; - size += has_key() ? kTagSize + KeyWireHandler::ByteSize(key()) : 0; - size += has_value() ? kTagSize + ValueWireHandler::ByteSize(value()) : 0; + size += has_key() ? kTagSize + KeyTypeHandler::ByteSize(key()) : 0; + size += has_value() ? kTagSize + ValueTypeHandler::ByteSize(value()) : 0; return size; } void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const { - KeyWireHandler::Write(kKeyFieldNumber, key(), output); - ValueWireHandler::Write(kValueFieldNumber, value(), output); + KeyTypeHandler::Write(kKeyFieldNumber, key(), output); + ValueTypeHandler::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); + output = KeyTypeHandler::WriteToArray(kKeyFieldNumber, key(), output); + output = ValueTypeHandler::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; + size += has_key() + ? kTagSize + KeyTypeHandler::GetCachedSize(key()) + : 0; + size += has_value() + ? kTagSize + ValueTypeHandler::GetCachedSize( + value()) + : 0; return size; } - bool IsInitialized() const { return ValueCppHandler::IsInitialized(value_); } + bool IsInitialized() const { return ValueTypeHandler::IsInitialized(value_); } MessageLite* New() const { MapEntryLite* entry = new MapEntryLite; @@ -225,36 +214,37 @@ class MapEntryLite : public MessageLite { int SpaceUsed() const { int size = sizeof(MapEntryLite); - size += KeyCppHandler::SpaceUsedInMapEntry(key_); - size += ValueCppHandler::SpaceUsedInMapEntry(value_); + size += KeyTypeHandler::SpaceUsedInMapEntry(key_); + size += ValueTypeHandler::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_); + KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual()); + KeyTypeHandler::Merge(from.key(), &key_, GetArenaNoVirtual()); set_has_key(); } if (from.has_value()) { - ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual()); - ValueCppHandler::Merge(from.value(), &value_); + ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual()); + ValueTypeHandler::Merge(from.value(), &value_, GetArenaNoVirtual()); set_has_value(); } } } void Clear() { - KeyCppHandler::Clear(&key_); - ValueCppHandler::ClearMaybeByDefaultEnum(&value_, default_enum_value); + KeyTypeHandler::Clear(&key_, GetArenaNoVirtual()); + ValueTypeHandler::ClearMaybeByDefaultEnum( + &value_, GetArenaNoVirtual(), default_enum_value); clear_has_key(); clear_has_value(); } void InitAsDefaultInstance() { - KeyCppHandler::AssignDefaultValue(&key_); - ValueCppHandler::AssignDefaultValue(&value_); + KeyTypeHandler::AssignDefaultValue(&key_); + ValueTypeHandler::AssignDefaultValue(&value_); } Arena* GetArena() const { @@ -302,11 +292,11 @@ class MapEntryLite : public MessageLite { // only takes references of given key and value. template - class MapEntryWrapper + class LIBPROTOBUF_EXPORT MapEntryWrapper : public MapEntryLite { typedef MapEntryLite Base; - typedef typename Base::KeyCppType KeyCppType; - typedef typename Base::ValCppType ValCppType; + typedef typename Base::KeyMapEntryAccessorType KeyMapEntryAccessorType; + typedef typename Base::ValueMapEntryAccessorType ValueMapEntryAccessorType; public: MapEntryWrapper(Arena* arena, const K& key, const V& value) @@ -316,8 +306,8 @@ class MapEntryLite : public MessageLite { Base::set_has_key(); Base::set_has_value(); } - inline const KeyCppType& key() const { return key_; } - inline const ValCppType& value() const { return value_; } + inline const KeyMapEntryAccessorType& key() const { return key_; } + inline const ValueMapEntryAccessorType& value() const { return value_; } private: const Key& key_; @@ -336,11 +326,11 @@ class MapEntryLite : public MessageLite { // the temporary. template - class MapEnumEntryWrapper + class LIBPROTOBUF_EXPORT MapEnumEntryWrapper : public MapEntryLite { typedef MapEntryLite Base; - typedef typename Base::KeyCppType KeyCppType; - typedef typename Base::ValCppType ValCppType; + typedef typename Base::KeyMapEntryAccessorType KeyMapEntryAccessorType; + typedef typename Base::ValueMapEntryAccessorType ValueMapEntryAccessorType; public: MapEnumEntryWrapper(Arena* arena, const K& key, const V& value) @@ -350,28 +340,28 @@ class MapEntryLite : public MessageLite { Base::set_has_key(); Base::set_has_value(); } - inline const KeyCppType& key() const { return key_; } - inline const ValCppType& value() const { return value_; } + inline const KeyMapEntryAccessorType& key() const { return key_; } + inline const ValueMapEntryAccessorType& value() const { return value_; } private: - const KeyCppType& key_; - const ValCppType value_; + const KeyMapEntryAccessorType& key_; + const ValueMapEntryAccessorType value_; friend class google::protobuf::Arena; typedef void DestructorSkippable_; }; MapEntryLite() : default_instance_(NULL), arena_(NULL) { - KeyCppHandler::Initialize(&key_, NULL); - ValueCppHandler::InitializeMaybeByDefaultEnum( + KeyTypeHandler::Initialize(&key_, NULL); + ValueTypeHandler::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( + KeyTypeHandler::Initialize(&key_, arena); + ValueTypeHandler::InitializeMaybeByDefaultEnum( &value_, default_enum_value, arena); _has_bits_[0] = 0; } @@ -386,8 +376,8 @@ class MapEntryLite : public MessageLite { MapEntryLite* default_instance_; - KeyBase key_; - ValueBase value_; + KeyOnMemory key_; + ValueOnMemory value_; Arena* arena_; uint32 _has_bits_[1]; diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc index 6ff1936e..d8879f24 100644 --- a/src/google/protobuf/map_field.cc +++ b/src/google/protobuf/map_field.cc @@ -29,6 +29,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include #include @@ -145,6 +146,321 @@ void MapFieldBase::SyncMapWithRepeatedField() const { } } +// ------------------DynamicMapField------------------ +DynamicMapField::DynamicMapField(const Message* default_entry) + : default_entry_(default_entry) { +} + +DynamicMapField::DynamicMapField(const Message* default_entry, + Arena* arena) + : TypeDefinedMapFieldBase(arena), + default_entry_(default_entry) { +} + +DynamicMapField::~DynamicMapField() { + // DynamicMapField owns map values. Need to delete them before clearing + // the map. + for (typename Map::iterator iter = map_.begin(); + iter != map_.end(); ++iter) { + iter->second.DeleteData(); + } + map_.clear(); +} + +int DynamicMapField::size() const { + return GetMap().size(); +} + +bool DynamicMapField::ContainsMapKey( + const MapKey& map_key) const { + const Map& map = GetMap(); + typename Map::const_iterator iter = map.find(map_key); + return iter != map.end(); +} + +bool DynamicMapField::InsertMapValue( + const MapKey& map_key, MapValueRef* val) { + bool result = false; + + MapValueRef& map_val = (*MutableMap())[map_key]; + // If map_val.data_ is not set, it is newly inserted by map_[map_key]. + if (map_val.data_ == NULL) { + result = true; + const FieldDescriptor* val_des = + default_entry_->GetDescriptor()->FindFieldByName("value"); + map_val.SetType(val_des->cpp_type()); + // Allocate momery for the inserted MapValueRef, and initialize to + // default value. + switch (val_des->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + TYPE * value = new TYPE(); \ + map_val.SetValue(value); \ + break; \ + } + HANDLE_TYPE(INT32, int32); + HANDLE_TYPE(INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(STRING, string); + HANDLE_TYPE(ENUM, int32); +#undef HANDLE_TYPE + case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: { + const Message& message = default_entry_->GetReflection()->GetMessage( + *default_entry_, val_des); + Message* value = message.New(); + map_val.SetValue(value); + break; + } + } + } + val->CopyFrom(map_val); + return result; +} + +bool DynamicMapField::DeleteMapValue(const MapKey& map_key) { + MapFieldBase::SyncMapWithRepeatedField(); + Map::iterator iter = map_.find(map_key); + if (iter == map_.end()) { + return false; + } + // Set map dirty only if the delete is successful. + MapFieldBase::SetMapDirty(); + iter->second.DeleteData(); + map_.erase(iter); + return true; +} + +const Map& DynamicMapField::GetMap() const { + MapFieldBase::SyncMapWithRepeatedField(); + return map_; +} + +Map* DynamicMapField::MutableMap() { + MapFieldBase::SyncMapWithRepeatedField(); + MapFieldBase::SetMapDirty(); + return &map_; +} + +void DynamicMapField::SetMapIteratorValue(MapIterator* map_iter) const { + typename Map::const_iterator iter = + TypeDefinedMapFieldBase::InternalGetIterator( + map_iter); + if (iter == map_.end()) return; + map_iter->key_.CopyFrom(iter->first); + map_iter->value_.CopyFrom(iter->second); +} + +void DynamicMapField::SyncRepeatedFieldWithMapNoLock() const { + const Reflection* reflection = default_entry_->GetReflection(); + const FieldDescriptor* key_des = + default_entry_->GetDescriptor()->FindFieldByName("key"); + const FieldDescriptor* val_des = + default_entry_->GetDescriptor()->FindFieldByName("value"); + if (MapFieldBase::repeated_field_ == NULL) { + if (MapFieldBase::arena_ == NULL) { + MapFieldBase::repeated_field_ = new RepeatedPtrField(); + } else { + MapFieldBase::repeated_field_ = + Arena::CreateMessage >( + MapFieldBase::arena_); + } + } + + MapFieldBase::repeated_field_->Clear(); + + for (typename Map::const_iterator it = map_.begin(); + it != map_.end(); ++it) { + Message* new_entry = default_entry_->New(); + MapFieldBase::repeated_field_->AddAllocated(new_entry); + const MapKey& map_key = it->first; + switch (key_des->cpp_type()) { + case google::protobuf::FieldDescriptor::CPPTYPE_STRING: + reflection->SetString(new_entry, key_des, map_key.GetStringValue()); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_INT64: + reflection->SetInt64(new_entry, key_des, map_key.GetInt64Value()); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_INT32: + reflection->SetInt32(new_entry, key_des, map_key.GetInt32Value()); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: + reflection->SetUInt64(new_entry, key_des, map_key.GetUInt64Value()); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: + reflection->SetUInt32(new_entry, key_des, map_key.GetUInt32Value()); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: + reflection->SetBool(new_entry, key_des, map_key.GetBoolValue()); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: + case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: + case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: + case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Can't get here."; + break; + } + const MapValueRef& map_val = it->second; + switch (val_des->cpp_type()) { + case google::protobuf::FieldDescriptor::CPPTYPE_STRING: + reflection->SetString(new_entry, val_des, map_val.GetStringValue()); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_INT64: + reflection->SetInt64(new_entry, val_des, map_val.GetInt64Value()); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_INT32: + reflection->SetInt32(new_entry, val_des, map_val.GetInt32Value()); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: + reflection->SetUInt64(new_entry, val_des, map_val.GetUInt64Value()); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: + reflection->SetUInt32(new_entry, val_des, map_val.GetUInt32Value()); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: + reflection->SetBool(new_entry, val_des, map_val.GetBoolValue()); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: + reflection->SetDouble(new_entry, val_des, map_val.GetDoubleValue()); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: + reflection->SetFloat(new_entry, val_des, map_val.GetFloatValue()); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: + reflection->SetEnumValue(new_entry, val_des, map_val.GetEnumValue()); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: { + const Message& message = map_val.GetMessageValue(); + reflection->MutableMessage(new_entry, val_des)->CopyFrom(message); + break; + } + } + } +} + +void DynamicMapField::SyncMapWithRepeatedFieldNoLock() const { + Map* map = &const_cast(this)->map_; + const Reflection* reflection = default_entry_->GetReflection(); + const FieldDescriptor* key_des = + default_entry_->GetDescriptor()->FindFieldByName("key"); + const FieldDescriptor* val_des = + default_entry_->GetDescriptor()->FindFieldByName("value"); + // DynamicMapField owns map values. Need to delete them before clearing + // the map. + for (typename Map::iterator iter = map->begin(); + iter != map->end(); ++iter) { + iter->second.DeleteData(); + } + map->clear(); + for (typename RepeatedPtrField::iterator it = + MapFieldBase::repeated_field_->begin(); + it != MapFieldBase::repeated_field_->end(); ++it) { + MapKey map_key; + switch (key_des->cpp_type()) { + case google::protobuf::FieldDescriptor::CPPTYPE_STRING: + map_key.SetStringValue(reflection->GetString(*it, key_des)); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_INT64: + map_key.SetInt64Value(reflection->GetInt64(*it, key_des)); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_INT32: + map_key.SetInt32Value(reflection->GetInt32(*it, key_des)); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: + map_key.SetUInt64Value(reflection->GetUInt64(*it, key_des)); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: + map_key.SetUInt32Value(reflection->GetUInt32(*it, key_des)); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: + map_key.SetBoolValue(reflection->GetBool(*it, key_des)); + break; + case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: + case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: + case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: + case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Can't get here."; + break; + } + MapValueRef& map_val = (*map)[map_key]; + map_val.SetType(val_des->cpp_type()); + switch (val_des->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, TYPE, METHOD) \ + case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + TYPE * value = new TYPE; \ + *value = reflection->Get##METHOD(*it, val_des); \ + map_val.SetValue(value); \ + break; \ + } + HANDLE_TYPE(INT32, int32, Int32); + HANDLE_TYPE(INT64, int64, Int64); + HANDLE_TYPE(UINT32, uint32, UInt32); + HANDLE_TYPE(UINT64, uint64, UInt64); + HANDLE_TYPE(DOUBLE, double, Double); + HANDLE_TYPE(FLOAT, float, Float); + HANDLE_TYPE(BOOL, bool, Bool); + HANDLE_TYPE(STRING, string, String); + HANDLE_TYPE(ENUM, int32, EnumValue); +#undef HANDLE_TYPE + case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: { + const Message& message = reflection->GetMessage(*it, val_des); + Message* value = message.New(); + value->CopyFrom(message); + map_val.SetValue(value); + break; + } + } + } +} + +int DynamicMapField::SpaceUsedExcludingSelfNoLock() const { + int size = 0; + if (MapFieldBase::repeated_field_ != NULL) { + size += MapFieldBase::repeated_field_->SpaceUsedExcludingSelf(); + } + size += sizeof(map_); + int map_size = map_.size(); + if (map_size) { + typename Map::const_iterator it = map_.begin(); + size += sizeof(it->first) * map_size; + size += sizeof(it->second) * map_size; + // If key is string, add the allocated space. + if (it->first.type() == google::protobuf::FieldDescriptor::CPPTYPE_STRING) { + size += sizeof(string) * map_size; + } + // Add the allocated space in MapValueRef. + switch (it->second.type()) { +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + size += sizeof(TYPE) * map_size; \ + break; \ + } + HANDLE_TYPE(INT32, int32); + HANDLE_TYPE(INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(STRING, string); + HANDLE_TYPE(ENUM, int32); +#undef HANDLE_TYPE + case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: { + while (it != map_.end()) { + const Message& message = it->second.GetMessageValue(); + size += message.GetReflection()->SpaceUsed(message); + ++it; + } + break; + } + } + } + return size; +} + } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h index 56d3d0f4..9130166b 100644 --- a/src/google/protobuf/map_field.h +++ b/src/google/protobuf/map_field.h @@ -32,6 +32,7 @@ #define GOOGLE_PROTOBUF_MAP_FIELD_H__ #include +#include #include #include #include @@ -45,7 +46,8 @@ namespace google { namespace protobuf { - +class DynamicMessage; +class MapKey; namespace internal { class ContendedMapCleanTest; @@ -83,6 +85,17 @@ class LIBPROTOBUF_EXPORT MapFieldBase { // Like above. Returns mutable pointer to the internal repeated field. RepeatedPtrFieldBase* MutableRepeatedField(); + // Pure virtual map APIs for Map Reflection. + virtual bool ContainsMapKey(const MapKey& map_key) const = 0; + virtual bool InsertMapValue(const MapKey& map_key, MapValueRef* val) = 0; + virtual bool DeleteMapValue(const MapKey& map_key) = 0; + virtual bool EqualIterator(const MapIterator& a, + const MapIterator& b) const = 0; + virtual void MapBegin(MapIterator* map_iter) const = 0; + virtual void MapEnd(MapIterator* map_iter) const = 0; + // Sync Map with repeated field and returns the size of map. + virtual int size() const = 0; + // Returns the number of bytes used by the repeated field, excluding // sizeof(*this) int SpaceUsedExcludingSelf() const; @@ -141,6 +154,57 @@ class LIBPROTOBUF_EXPORT MapFieldBase { friend class ContendedMapCleanTest; friend class GeneratedMessageReflection; friend class MapFieldAccessor; + friend class ::google::protobuf::DynamicMessage; + + // Virtual helper methods for MapIterator. MapIterator doesn't have the + // type helper for key and value. Call these help methods to deal with + // different types. Real helper methods are implemented in + // TypeDefinedMapFieldBase. + friend class ::google::protobuf::MapIterator; + // Allocate map<...>::iterator for MapIterator. + virtual void InitializeIterator(MapIterator* map_iter) const = 0; + + // DeleteIterator() is called by the destructor of MapIterator only. + // It deletes map<...>::iterator for MapIterator. + virtual void DeleteIterator(MapIterator* map_iter) const = 0; + + // Copy the map<...>::iterator from other_iterator to + // this_iterator. + virtual void CopyIterator(MapIterator* this_iterator, + const MapIterator& other_iterator) const = 0; + + // IncreaseIterator() is called by operator++() of MapIterator only. + // It implements the ++ operator of MapIterator. + virtual void IncreaseIterator(MapIterator* map_iter) const = 0; +}; + +// This class provides common Map Reflection implementations for generated +// message and dynamic message. +template +class TypeDefinedMapFieldBase : public MapFieldBase { + public: + TypeDefinedMapFieldBase() {} + explicit TypeDefinedMapFieldBase(Arena* arena) : MapFieldBase(arena) {} + ~TypeDefinedMapFieldBase() {} + void MapBegin(MapIterator* map_iter) const; + void MapEnd(MapIterator* map_iter) const; + bool EqualIterator(const MapIterator& a, const MapIterator& b) const; + + virtual const Map& GetMap() const = 0; + virtual Map* MutableMap() = 0; + + protected: + typename Map::const_iterator& InternalGetIterator( + const MapIterator* map_iter) const; + + private: + void InitializeIterator(MapIterator* map_iter) const; + void DeleteIterator(MapIterator* map_iter) const; + void CopyIterator(MapIterator* this_iteratorm, + const MapIterator& that_iterator) const; + void IncreaseIterator(MapIterator* map_iter) const; + + virtual void SetMapIteratorValue(MapIterator* map_iter) const = 0; }; // This class provides accesss to map field using generated api. It is used for @@ -150,25 +214,13 @@ template -class MapField : public MapFieldBase, +class MapField : public TypeDefinedMapFieldBase, public MapFieldLite { - // Handlers for key/value wire type. Provide utilities to parse/serialize - // key/value. - typedef MapWireFieldTypeHandler KeyWireHandler; - typedef MapWireFieldTypeHandler ValueWireHandler; - - // Define key/value's internal stored type. - 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::type KeyCpp; - typedef typename MapIf::type ValCpp; - - // Handlers for key/value's internal stored type. - typedef MapCppTypeHandler KeyHandler; - typedef MapCppTypeHandler ValHandler; + // Provide utilities to parse/serialize key/value. Provide utilities to + // manipulate internal stored type. + typedef MapTypeHandler KeyTypeHandler; + typedef MapTypeHandler ValueTypeHandler; // Define message type for internal repeated field. typedef MapEntry @@ -183,8 +235,8 @@ class MapField : public MapFieldBase, // 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 = ValueWireHandler::kIsEnum; + // SyncMapWithRepeatedFieldNoLock. + static const bool kIsValueEnum = ValueTypeHandler::kIsEnum; typedef typename MapIf::type CastValueType; public: @@ -197,6 +249,11 @@ class MapField : public MapFieldBase, MapField(Arena* arena, const Message* default_entry); ~MapField(); + // Implement MapFieldBase + bool ContainsMapKey(const MapKey& map_key) const; + bool InsertMapValue(const MapKey& map_key, MapValueRef* val); + bool DeleteMapValue(const MapKey& map_key); + // Accessors const Map& GetMap() const; Map* MutableMap(); @@ -230,12 +287,109 @@ class MapField : public MapFieldBase, void SyncMapWithRepeatedFieldNoLock() const; int SpaceUsedExcludingSelfNoLock() const; + void SetMapIteratorValue(MapIterator* map_iter) const; + mutable const EntryType* default_entry_; friend class ::google::protobuf::Arena; }; +class LIBPROTOBUF_EXPORT DynamicMapField: public TypeDefinedMapFieldBase { + public: + explicit DynamicMapField(const Message* default_entry); + DynamicMapField(const Message* default_entry, Arena* arena); + ~DynamicMapField(); + + // Implement MapFieldBase + bool ContainsMapKey(const MapKey& map_key) const; + bool InsertMapValue(const MapKey& map_key, MapValueRef* val); + bool DeleteMapValue(const MapKey& map_key); + + const Map& GetMap() const; + Map* MutableMap(); + + int size() const; + + private: + Map map_; + const Message* default_entry_; + + // Implements MapFieldBase + void SyncRepeatedFieldWithMapNoLock() const; + void SyncMapWithRepeatedFieldNoLock() const; + int SpaceUsedExcludingSelfNoLock() const; + void SetMapIteratorValue(MapIterator* map_iter) const; +}; + } // namespace internal + +class LIBPROTOBUF_EXPORT MapIterator { + public: + MapIterator(Message* message, const FieldDescriptor* field) { + const Reflection* reflection = message->GetReflection(); + map_ = reflection->MapData(message, field); + key_.SetType(field->message_type()->FindFieldByName("key")->cpp_type()); + value_.SetType(field->message_type()->FindFieldByName("value")->cpp_type()); + map_->InitializeIterator(this); + } + MapIterator(const MapIterator& other) { + map_ = other.map_; + map_->InitializeIterator(this); + map_->CopyIterator(this, other); + } + ~MapIterator() { + map_->DeleteIterator(this); + } + friend bool operator==(const MapIterator& a, const MapIterator& b) { + return a.map_->EqualIterator(a, b); + } + friend bool operator!=(const MapIterator& a, const MapIterator& b) { + return !a.map_->EqualIterator(a, b); + } + MapIterator& operator++() { + map_->IncreaseIterator(this); + return *this; + } + MapIterator operator++(int) { + // iter_ is copied from Map<...>::iterator, no need to + // copy from its self again. Use the same implementation + // with operator++() + map_->IncreaseIterator(this); + return *this; + } + const MapKey& GetKey() { + return key_; + } + const MapValueRef& GetValueRef() { + return value_; + } + MapValueRef* MutableValueRef() { + map_->SetMapDirty(); + return &value_; + } + + private: + template + friend class internal::TypeDefinedMapFieldBase; + friend class internal::DynamicMapField; + template + friend class internal::MapField; + + // reinterpret_cast from heap-allocated Map<...>::iterator*. MapIterator owns + // the iterator. It is allocated by MapField<...>::InitializeIterator() called + // in constructor and deleted by MapField<...>::DeleteIterator() called in + // destructor. + void* iter_; + // Point to a MapField to call helper methods implemented in MapField. + // MapIterator does not own this object. + internal::MapFieldBase* map_; + MapKey key_; + MapValueRef value_; +}; + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h index 5b4305f9..1a4ce937 100644 --- a/src/google/protobuf/map_field_inl.h +++ b/src/google/protobuf/map_field_inl.h @@ -36,12 +36,128 @@ #include #endif +#include #include #include namespace google { namespace protobuf { namespace internal { +// UnwrapMapKey template +template +T UnwrapMapKey(const MapKey& map_key); +template<> +inline int32 UnwrapMapKey(const MapKey& map_key) { + return map_key.GetInt32Value(); +} +template<> +inline uint32 UnwrapMapKey(const MapKey& map_key) { + return map_key.GetUInt32Value(); +} +template<> +inline int64 UnwrapMapKey(const MapKey& map_key) { + return map_key.GetInt64Value(); +} +template<> +inline uint64 UnwrapMapKey(const MapKey& map_key) { + return map_key.GetUInt64Value(); +} +template<> +inline bool UnwrapMapKey(const MapKey& map_key) { + return map_key.GetBoolValue(); +} +template<> +inline string UnwrapMapKey(const MapKey& map_key) { + return map_key.GetStringValue(); +} + +// SetMapKey template +template +inline void SetMapKey(MapKey* map_key, const T& value); +template<> +inline void SetMapKey(MapKey* map_key, const int32& value) { + map_key->SetInt32Value(value); +} +template<> +inline void SetMapKey(MapKey* map_key, const uint32& value) { + map_key->SetUInt32Value(value); +} +template<> +inline void SetMapKey(MapKey* map_key, const int64& value) { + map_key->SetInt64Value(value); +} +template<> +inline void SetMapKey(MapKey* map_key, const uint64& value) { + map_key->SetUInt64Value(value); +} +template<> +inline void SetMapKey(MapKey* map_key, const bool& value) { + map_key->SetBoolValue(value); +} +template<> +inline void SetMapKey(MapKey* map_key, const string& value) { + map_key->SetStringValue(value); +} + +// ------------------------TypeDefinedMapFieldBase--------------- +template +typename Map::const_iterator& +TypeDefinedMapFieldBase::InternalGetIterator( + const MapIterator* map_iter) const { + return *reinterpret_cast::const_iterator *>( + map_iter->iter_); +} + +template +void TypeDefinedMapFieldBase::MapBegin(MapIterator* map_iter) const { + InternalGetIterator(map_iter) = GetMap().begin(); + SetMapIteratorValue(map_iter); +} + +template +void TypeDefinedMapFieldBase::MapEnd(MapIterator* map_iter) const { + InternalGetIterator(map_iter) = GetMap().end(); +} + +template +bool TypeDefinedMapFieldBase::EqualIterator(const MapIterator& a, + const MapIterator& b) + const { + return InternalGetIterator(&a) == InternalGetIterator(&b); +} + +template +void TypeDefinedMapFieldBase::IncreaseIterator(MapIterator* map_iter) + const { + ++InternalGetIterator(map_iter); + SetMapIteratorValue(map_iter); +} + +template +void TypeDefinedMapFieldBase::InitializeIterator( + MapIterator* map_iter) const { + map_iter->iter_ = new typename Map::const_iterator; + GOOGLE_CHECK(map_iter->iter_ != NULL); +} + +template +void TypeDefinedMapFieldBase::DeleteIterator(MapIterator* map_iter) + const { + delete reinterpret_cast::const_iterator *>( + map_iter->iter_); +} + +template +void TypeDefinedMapFieldBase::CopyIterator( + MapIterator* this_iter, + const MapIterator& that_iter) const { + InternalGetIterator(this_iter) = InternalGetIterator(&that_iter); + this_iter->key_.SetType(that_iter.key_.type()); + this_iter->value_.SetType(that_iter.value_.type()); + SetMapIteratorValue(this_iter); +} + +// ---------------------------------------------------------------------- template MapField::MapField( Arena* arena) - : MapFieldBase(arena), + : TypeDefinedMapFieldBase(arena), MapFieldLite( arena), default_entry_(NULL) {} @@ -75,7 +191,7 @@ template MapField::MapField( Arena* arena, const Message* default_entry) - : MapFieldBase(arena), + : TypeDefinedMapFieldBase(arena), MapFieldLite( arena), default_entry_(down_cast(default_entry)) {} @@ -94,7 +210,7 @@ template ::size() const { - SyncMapWithRepeatedField(); + MapFieldBase::SyncMapWithRepeatedField(); return MapFieldLiteType::GetInternalMap().size(); } @@ -105,9 +221,65 @@ template ::Clear() { - SyncMapWithRepeatedField(); + MapFieldBase::SyncMapWithRepeatedField(); MapFieldLiteType::MutableInternalMap()->clear(); - SetMapDirty(); + MapFieldBase::SetMapDirty(); +} + +template +void MapField::SetMapIteratorValue( + MapIterator* map_iter) const { + const Map& map = GetMap(); + typename Map::const_iterator iter = + TypeDefinedMapFieldBase::InternalGetIterator(map_iter); + if (iter == map.end()) return; + SetMapKey(&map_iter->key_, iter->first); + map_iter->value_.SetValue(&iter->second); +} + +template +bool MapField::ContainsMapKey( + const MapKey& map_key) const { + const Map& map = GetMap(); + const Key& key = UnwrapMapKey(map_key); + typename Map::const_iterator iter = map.find(key); + return iter != map.end(); +} + +template +bool MapField::InsertMapValue(const MapKey& map_key, + MapValueRef* val) { + Map* map = MutableMap(); + bool result = false; + const Key& key = UnwrapMapKey(map_key); + if (map->end() == map->find(key)) { + result = true; + } + val->SetValue(&((*map)[key])); + return result; +} + +template +bool MapField::DeleteMapValue( + const MapKey& map_key) { + const Key& key = UnwrapMapKey(map_key); + return MutableMap()->erase(key); } template & MapField::GetMap() const { - SyncMapWithRepeatedField(); + MapFieldBase::SyncMapWithRepeatedField(); return MapFieldLiteType::GetInternalMap(); } @@ -128,9 +300,9 @@ template * MapField::MutableMap() { - SyncMapWithRepeatedField(); + MapFieldBase::SyncMapWithRepeatedField(); Map* result = MapFieldLiteType::MutableInternalMap(); - SetMapDirty(); + MapFieldBase::SetMapDirty(); return result; } @@ -143,10 +315,10 @@ MapField::MergeFrom( const MapFieldLiteType& other) { const MapField& down_other = down_cast(other); - SyncMapWithRepeatedField(); + MapFieldBase::SyncMapWithRepeatedField(); down_other.SyncMapWithRepeatedField(); MapFieldLiteType::MergeFrom(other); - SetMapDirty(); + MapFieldBase::SetMapDirty(); } template ::Swap( MapFieldLiteType* other) { MapField* down_other = down_cast(other); - std::swap(repeated_field_, down_other->repeated_field_); + std::swap(MapFieldBase::repeated_field_, down_other->repeated_field_); MapFieldLiteType::Swap(other); - std::swap(state_, down_other->state_); + std::swap(MapFieldBase::state_, down_other->state_); } template ::SetEntryDescriptor( const Descriptor** descriptor) { - entry_descriptor_ = descriptor; + MapFieldBase::entry_descriptor_ = descriptor; } template ::SetAssignDescriptorCallback(void (*callback)()) { - assign_descriptor_callback_ = callback; + MapFieldBase::assign_descriptor_callback_ = callback; } template ::SyncRepeatedFieldWithMapNoLock() const { - if (repeated_field_ == NULL) { + if (MapFieldBase::repeated_field_ == NULL) { if (MapFieldBase::arena_ == NULL) { - repeated_field_ = new RepeatedPtrField(); + MapFieldBase::repeated_field_ = new RepeatedPtrField(); } else { - repeated_field_ = Arena::CreateMessage >( - MapFieldBase::arena_); + MapFieldBase::repeated_field_ = + Arena::CreateMessage >( + MapFieldBase::arena_); } } const Map& map = GetInternalMap(); RepeatedPtrField* repeated_field = - reinterpret_cast*>(repeated_field_); + reinterpret_cast*>( + MapFieldBase::repeated_field_); repeated_field->Clear(); @@ -246,7 +420,9 @@ MapField::SyncMapWithRepeatedFieldNoLock() const { Map* map = const_cast(this)->MutableInternalMap(); RepeatedPtrField* repeated_field = - reinterpret_cast*>(repeated_field_); + reinterpret_cast*>( + MapFieldBase::repeated_field_); + GOOGLE_CHECK(MapFieldBase::repeated_field_ != NULL); map->clear(); for (typename RepeatedPtrField::iterator it = repeated_field->begin(); it != repeated_field->end(); ++it) { @@ -267,15 +443,15 @@ int MapField::SpaceUsedExcludingSelfNoLock() const { int size = 0; - if (repeated_field_ != NULL) { - size += repeated_field_->SpaceUsedExcludingSelf(); + if (MapFieldBase::repeated_field_ != NULL) { + size += MapFieldBase::repeated_field_->SpaceUsedExcludingSelf(); } Map* map = const_cast(this)->MutableInternalMap(); size += sizeof(*map); for (typename Map::iterator it = map->begin(); it != map->end(); ++it) { - size += KeyHandler::SpaceUsedInMap(it->first); - size += ValHandler::SpaceUsedInMap(it->second); + size += KeyTypeHandler::SpaceUsedInMap(it->first); + size += ValueTypeHandler::SpaceUsedInMap(it->second); } return size; } @@ -289,10 +465,11 @@ MapField::InitDefaultEntryOnce() const { if (default_entry_ == NULL) { - InitMetadataOnce(); - GOOGLE_CHECK(*entry_descriptor_ != NULL); + MapFieldBase::InitMetadataOnce(); + GOOGLE_CHECK(*MapFieldBase::entry_descriptor_ != NULL); default_entry_ = down_cast( - MessageFactory::generated_factory()->GetPrototype(*entry_descriptor_)); + MessageFactory::generated_factory()->GetPrototype( + *MapFieldBase::entry_descriptor_)); } } diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc index e3a64079..2ff1d6bb 100644 --- a/src/google/protobuf/map_field_test.cc +++ b/src/google/protobuf/map_field_test.cc @@ -34,6 +34,7 @@ #include #endif +#include #include #include #include @@ -74,6 +75,28 @@ class MapFieldBaseStub : public MapFieldBase { bool IsRepeatedClean() { return state_ != 1; } void SetMapDirty() { state_ = 0; } void SetRepeatedDirty() { state_ = 1; } + bool ContainsMapKey(const MapKey& map_key) const { + return false; + } + bool InsertMapValue(const MapKey& map_key, MapValueRef* val) { + return false; + } + bool DeleteMapValue(const MapKey& map_key) { + return false; + } + bool EqualIterator(const MapIterator& a, const MapIterator& b) const { + return false; + } + int size() const { return 0; } + void MapBegin(MapIterator* map_iter) const {} + void MapEnd(MapIterator* map_iter) const {} + void InitializeIterator(MapIterator* map_iter) const {} + void DeleteIterator(MapIterator* map_iter) const {} + void CopyIterator(MapIterator* this_iterator, + const MapIterator& other_iterator) const {} + void IncreaseIterator(MapIterator* map_iter) const {} + void SetDefaultMessageEntry(const Message* message) const {} + const Message* GetDefaultMessageEntry() const { return NULL; } }; class MapFieldBasePrimitiveTest : public ::testing::Test { diff --git a/src/google/protobuf/map_lite_unittest.proto b/src/google/protobuf/map_lite_unittest.proto index c69e8d94..0592dd7a 100644 --- a/src/google/protobuf/map_lite_unittest.proto +++ b/src/google/protobuf/map_lite_unittest.proto @@ -34,6 +34,7 @@ option cc_enable_arenas = true; option optimize_for = LITE_RUNTIME; import "google/protobuf/unittest_lite.proto"; +import "google/protobuf/unittest_no_arena_lite.proto"; package protobuf_unittest; @@ -72,8 +73,12 @@ message TestArenaMapLite { map map_int32_float = 11; map map_int32_double = 12; map map_bool_bool = 13; - map map_int32_enum = 14; - map map_int32_foreign_message = 15; + map map_string_string = 14; + map map_int32_bytes = 15; + map map_int32_enum = 16; + map map_int32_foreign_message = 17; + map + map_int32_foreign_message_no_arena = 18; } // Test embeded message with required fields @@ -81,10 +86,6 @@ message TestRequiredMessageMapLite { map map_field = 1; } -message TestEnumStartWithNonZeroMapLite { - map map_field = 101; -} - message TestEnumMapLite { map known_map_field = 101; map unknown_map_field = 102; @@ -112,10 +113,6 @@ enum Proto2MapEnumPlusExtraLite { 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; diff --git a/src/google/protobuf/map_proto2_unittest.proto b/src/google/protobuf/map_proto2_unittest.proto index 3d4af28e..6f9d6165 100644 --- a/src/google/protobuf/map_proto2_unittest.proto +++ b/src/google/protobuf/map_proto2_unittest.proto @@ -49,10 +49,6 @@ enum Proto2MapEnumPlusExtra { E_PROTO2_MAP_ENUM_EXTRA = 3; } -enum Proto2MapEnumStartWithNonZero { - PROTO2_NON_ZERO_MAP_ENUM_FOO = 1; -} - message TestEnumMap { map known_map_field = 101; map unknown_map_field = 102; @@ -62,7 +58,3 @@ message TestEnumMapPlusExtra { map known_map_field = 101; map unknown_map_field = 102; } - -message TestEnumStartWithNonZeroMap { - map map_field = 101; -} diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc index d62ec85f..a74801d9 100644 --- a/src/google/protobuf/map_test.cc +++ b/src/google/protobuf/map_test.cc @@ -36,7 +36,9 @@ #include #include +#include #include +#include #include #include #include @@ -70,6 +72,7 @@ namespace google { using google::protobuf::unittest::ForeignMessage; using google::protobuf::unittest::TestAllTypes; using google::protobuf::unittest::TestMap; +using google::protobuf::unittest::TestRecursiveMapMessage; namespace protobuf { namespace internal { @@ -200,6 +203,21 @@ TEST_F(MapImplTest, ImmutableAtNonExistDeathTest) { EXPECT_DEATH(const_map_.at(0), ""); } +TEST_F(MapImplTest, UsageErrors) { + MapKey key; + key.SetInt64Value(1); + EXPECT_DEATH(key.GetUInt64Value(), + "Protocol Buffer map usage error:\n" + "MapKey::GetUInt64Value type does not match\n" + " Expected : uint64\n" + " Actual : int64"); + + MapValueRef value; + EXPECT_DEATH(value.SetFloatValue(0.1), + "Protocol Buffer map usage error:\n" + "MapValueRef::type MapValueRef is not initialized."); +} + #endif // PROTOBUF_HAS_DEATH_TEST TEST_F(MapImplTest, CountNonExist) { @@ -475,6 +493,23 @@ TEST_F(MapImplTest, CopyConstructor) { EXPECT_EQ(value2, other.at(key2)); } +TEST_F(MapImplTest, IterConstructor) { + int32 key1 = 0; + int32 key2 = 1; + int32 value1 = 100; + int32 value2 = 101; + + std::map map; + map[key1] = value1; + map[key2] = value2; + + Map new_map(map.begin(), map.end()); + + EXPECT_EQ(2, new_map.size()); + EXPECT_EQ(value1, new_map.at(key1)); + EXPECT_EQ(value2, new_map.at(key2)); +} + TEST_F(MapImplTest, Assigner) { int32 key1 = 0; int32 key2 = 1; @@ -1140,6 +1175,19 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { mmf_int32_foreign_message.Add(*entry_int32_foreign_message); EXPECT_EQ(1234, message.map_int32_foreign_message().at(4321).c()); + // Test Reflection::AddAllocatedMessage + Message* free_entry_string_string = MessageFactory::generated_factory() + ->GetPrototype(fd_map_string_string->message_type()) + ->New(); + entry_string_string->GetReflection()->SetString( + free_entry_string_string, + fd_map_string_string->message_type()->field(0), "4321"); + entry_string_string->GetReflection()->SetString( + free_entry_string_string, fd_map_string_string->message_type()->field(1), + "1234"); + refl->AddAllocatedMessage(&message, fd_map_string_string, + free_entry_string_string); + // Test MutableRepeatedFieldRef::RemoveLast() mmf_int32_int32.RemoveLast(); mmf_int32_double.RemoveLast(); @@ -1147,7 +1195,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { mmf_int32_foreign_message.RemoveLast(); EXPECT_EQ(10, message.map_int32_int32().size()); EXPECT_EQ(10, message.map_int32_double().size()); - EXPECT_EQ(10, message.map_string_string().size()); + EXPECT_EQ(11, message.map_string_string().size()); EXPECT_EQ(10, message.map_int32_foreign_message().size()); // Test MutableRepeatedFieldRef::SwapElements() @@ -1398,9 +1446,9 @@ TEST(GeneratedMapFieldTest, SetMapFieldsInitialized) { } TEST(GeneratedMapFieldTest, Proto2SetMapFieldsInitialized) { - unittest::TestEnumStartWithNonZeroMap message; - EXPECT_EQ(unittest::PROTO2_NON_ZERO_MAP_ENUM_FOO, - (*message.mutable_map_field())[0]); + unittest::TestEnumMap message; + EXPECT_EQ(unittest::PROTO2_MAP_ENUM_FOO, + (*message.mutable_known_map_field())[0]); } TEST(GeneratedMapFieldTest, Clear) { @@ -1526,12 +1574,28 @@ TEST(GeneratedMapFieldTest, CopyFromDynamicMessage) { google::protobuf::scoped_ptr message1; message1.reset( factory.GetPrototype(unittest::TestMap::descriptor())->New()); - - MapTestUtil::MapReflectionTester reflection_tester( + MapReflectionTester reflection_tester( unittest::TestMap::descriptor()); reflection_tester.SetMapFieldsViaReflection(message1.get()); reflection_tester.ExpectMapFieldsSetViaReflection(*message1); + reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get()); + message2.CopyFrom(*message1); + MapTestUtil::ExpectMapFieldsSet(message2); +} + +TEST(GeneratedMapFieldTest, CopyFromDynamicMessageMapReflection) { + unittest::TestMap message2; + // Construct a new version of the dynamic message via the factory. + DynamicMessageFactory factory; + google::protobuf::scoped_ptr message1; + message1.reset( + factory.GetPrototype(unittest::TestMap::descriptor())->New()); + MapReflectionTester reflection_tester( + unittest::TestMap::descriptor()); + reflection_tester.SetMapFieldsViaMapReflection(message1.get()); + reflection_tester.ExpectMapFieldsSetViaReflection(*message1); + reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get()); message2.CopyFrom(*message1); MapTestUtil::ExpectMapFieldsSet(message2); } @@ -1547,12 +1611,43 @@ TEST(GeneratedMapFieldTest, DynamicMessageCopyFrom) { message1.reset( factory.GetPrototype(unittest::TestMap::descriptor())->New()); - MapTestUtil::MapReflectionTester reflection_tester( + MapReflectionTester reflection_tester( + unittest::TestMap::descriptor()); + message1->MergeFrom(message2); + reflection_tester.ExpectMapFieldsSetViaReflection(*message1); + reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get()); +} + +TEST(GeneratedMapFieldTest, DynamicMessageCopyFromMapReflection) { + MapReflectionTester reflection_tester( unittest::TestMap::descriptor()); + unittest::TestMap message2; + reflection_tester.SetMapFieldsViaMapReflection(&message2); + + // Construct a dynamic message via the factory. + DynamicMessageFactory factory; + google::protobuf::scoped_ptr message1; + message1.reset( + factory.GetPrototype(unittest::TestMap::descriptor())->New()); + message1->MergeFrom(message2); + reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get()); reflection_tester.ExpectMapFieldsSetViaReflection(*message1); } +TEST(GeneratedMapFieldTest, SyncDynamicMapWithRepeatedField) { + // Construct a dynamic message via the factory. + MapReflectionTester reflection_tester( + unittest::TestMap::descriptor()); + DynamicMessageFactory factory; + google::protobuf::scoped_ptr message; + message.reset( + factory.GetPrototype(unittest::TestMap::descriptor())->New()); + reflection_tester.SetMapFieldsViaReflection(message.get()); + reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message.get()); + reflection_tester.ExpectMapFieldsSetViaReflection(*message); +} + #endif // !PROTOBUF_TEST_NO_DESCRIPTORS TEST(GeneratedMapFieldTest, NonEmptyMergeFrom) { @@ -1779,7 +1874,7 @@ TEST(GeneratedMapFieldTest, IsInitialized) { TEST(GeneratedMapFieldReflectionTest, SpaceUsed) { unittest::TestMap message; - MapTestUtil::MapReflectionTester reflection_tester( + MapReflectionTester reflection_tester( unittest::TestMap::descriptor()); reflection_tester.SetMapFieldsViaReflection(&message); @@ -1790,11 +1885,12 @@ TEST(GeneratedMapFieldReflectionTest, Accessors) { // Set every field to a unique value then go back and check all those // values. unittest::TestMap message; - MapTestUtil::MapReflectionTester reflection_tester( + MapReflectionTester reflection_tester( unittest::TestMap::descriptor()); reflection_tester.SetMapFieldsViaReflection(&message); MapTestUtil::ExpectMapFieldsSet(message); reflection_tester.ExpectMapFieldsSetViaReflection(message); + reflection_tester.ExpectMapFieldsSetViaReflectionIterator(&message); reflection_tester.ModifyMapFieldsViaReflection(&message); MapTestUtil::ExpectMapFieldsModified(message); @@ -1848,15 +1944,16 @@ TEST(GeneratedMapFieldReflectionTest, ClearField) { MapTestUtil::SetMapFields(&message); MapTestUtil::ExpectMapFieldsSet(message); - MapTestUtil::MapReflectionTester reflection_tester( + MapReflectionTester reflection_tester( unittest::TestMap::descriptor()); reflection_tester.ClearMapFieldsViaReflection(&message); - MapTestUtil::ExpectClear(message); + reflection_tester.ExpectClearViaReflection(message); + reflection_tester.ExpectClearViaReflectionIterator(&message); } TEST(GeneratedMapFieldReflectionTest, RemoveLast) { unittest::TestMap message; - MapTestUtil::MapReflectionTester reflection_tester( + MapReflectionTester reflection_tester( unittest::TestMap::descriptor()); MapTestUtil::SetMapFields(&message); @@ -1875,7 +1972,7 @@ TEST(GeneratedMapFieldReflectionTest, RemoveLast) { TEST(GeneratedMapFieldReflectionTest, ReleaseLast) { unittest::TestMap message; const Descriptor* descriptor = message.GetDescriptor(); - MapTestUtil::MapReflectionTester reflection_tester(descriptor); + MapReflectionTester reflection_tester(descriptor); MapTestUtil::SetMapFields(&message); @@ -1904,7 +2001,7 @@ TEST(GeneratedMapFieldReflectionTest, ReleaseLast) { TEST(GeneratedMapFieldReflectionTest, SwapElements) { unittest::TestMap message; - MapTestUtil::MapReflectionTester reflection_tester( + MapReflectionTester reflection_tester( unittest::TestMap::descriptor()); MapTestUtil::SetMapFields(&message); @@ -1944,7 +2041,7 @@ TEST(GeneratedMapFieldReflectionTest, SwapElements) { TEST(GeneratedMapFieldReflectionTest, MutableUnknownFields) { unittest::TestMap message; - MapTestUtil::MapReflectionTester reflection_tester( + MapReflectionTester reflection_tester( unittest::TestMap::descriptor()); reflection_tester.MutableUnknownFieldsOfMapFieldsViaReflection(&message); } @@ -2000,24 +2097,35 @@ TEST(GeneratedMapFieldReflectionTest, MergeFromClearMapEntry) { TEST(GeneratedMapFieldReflectionTest, MapEntryClear) { unittest::TestMap message; - MapTestUtil::MapReflectionTester reflection_tester( + MapReflectionTester reflection_tester( unittest::TestMap::descriptor()); reflection_tester.MutableUnknownFieldsOfMapFieldsViaReflection(&message); } TEST(GeneratedMapFieldReflectionTest, Proto2MapEntryClear) { - unittest::TestEnumStartWithNonZeroMap message; + unittest::TestEnumMap message; const Descriptor* descriptor = message.GetDescriptor(); const FieldDescriptor* field_descriptor = - descriptor->FindFieldByName("map_field"); + descriptor->FindFieldByName("known_map_field"); const FieldDescriptor* value_descriptor = field_descriptor->message_type()->FindFieldByName("value"); Message* sub_message = message.GetReflection()->AddMessage(&message, field_descriptor); - EXPECT_EQ(1, sub_message->GetReflection()->GetEnumValue(*sub_message, + EXPECT_EQ(0, sub_message->GetReflection()->GetEnumValue(*sub_message, value_descriptor)); } +// Map Reflection API Test ========================================= + +TEST(GeneratedMapFieldReflectionTest, SetViaMapReflection) { + unittest::TestMap message; + MapReflectionTester reflection_tester( + unittest::TestMap::descriptor()); + reflection_tester.SetMapFieldsViaMapReflection(&message); + reflection_tester.ExpectMapFieldsSetViaReflection(message); + reflection_tester.ExpectMapFieldsSetViaReflectionIterator(&message); +} + // Dynamic Message Test ============================================= class MapFieldInDynamicMessageTest : public testing::Test { @@ -2025,6 +2133,7 @@ class MapFieldInDynamicMessageTest : public testing::Test { const DescriptorPool* pool_; DynamicMessageFactory factory_; const Descriptor* map_descriptor_; + const Descriptor* recursive_map_descriptor_; const Message* map_prototype_; MapFieldInDynamicMessageTest() @@ -2033,7 +2142,10 @@ class MapFieldInDynamicMessageTest : public testing::Test { virtual void SetUp() { map_descriptor_ = pool_->FindMessageTypeByName("protobuf_unittest.TestMap"); + recursive_map_descriptor_ = + pool_->FindMessageTypeByName("protobuf_unittest.TestRecursiveMapMessage"); ASSERT_TRUE(map_descriptor_ != NULL); + ASSERT_TRUE(recursive_map_descriptor_ != NULL); map_prototype_ = factory_.GetPrototype(map_descriptor_); } }; @@ -2043,19 +2155,19 @@ TEST_F(MapFieldInDynamicMessageTest, MapIndependentOffsets) { // one to a unique value then checking that they all still have those // unique values (i.e. they don't stomp each other). scoped_ptr message(map_prototype_->New()); - MapTestUtil::MapReflectionTester reflection_tester(map_descriptor_); + MapReflectionTester reflection_tester(map_descriptor_); reflection_tester.SetMapFieldsViaReflection(message.get()); reflection_tester.ExpectMapFieldsSetViaReflection(*message); } -TEST_F(MapFieldInDynamicMessageTest, Map) { +TEST_F(MapFieldInDynamicMessageTest, DynamicMapReflection) { // Check that map fields work properly. scoped_ptr message(map_prototype_->New()); // Check set functions. - MapTestUtil::MapReflectionTester reflection_tester(map_descriptor_); - reflection_tester.SetMapFieldsViaReflection(message.get()); + MapReflectionTester reflection_tester(map_descriptor_); + reflection_tester.SetMapFieldsViaMapReflection(message.get()); reflection_tester.ExpectMapFieldsSetViaReflection(*message); } @@ -2066,7 +2178,7 @@ TEST_F(MapFieldInDynamicMessageTest, MapSpaceUsed) { // to test very much here. Just make sure it appears to be working. scoped_ptr message(map_prototype_->New()); - MapTestUtil::MapReflectionTester reflection_tester(map_descriptor_); + MapReflectionTester reflection_tester(map_descriptor_); int initial_space_used = message->SpaceUsed(); @@ -2074,6 +2186,15 @@ TEST_F(MapFieldInDynamicMessageTest, MapSpaceUsed) { EXPECT_LT(initial_space_used, message->SpaceUsed()); } +TEST_F(MapFieldInDynamicMessageTest, RecursiveMap) { + TestRecursiveMapMessage from; + (*from.mutable_a())[0]; + string data = from.SerializeAsString(); + google::protobuf::scoped_ptr to( + factory_.GetPrototype(recursive_map_descriptor_)->New()); + ASSERT_TRUE(to->ParseFromString(data)); +} + // ReflectionOps Test =============================================== TEST(ReflectionOpsForMapFieldTest, MapSanityCheck) { @@ -2260,7 +2381,7 @@ TEST(TextFormatMapTest, SerializeAndParse) { TEST(TextFormatMapTest, Sorted) { unittest::TestMap message; - MapTestUtil::MapReflectionTester tester(message.GetDescriptor()); + MapReflectionTester tester(message.GetDescriptor()); tester.SetMapFieldsViaReflection(&message); string expected_text; @@ -2292,7 +2413,8 @@ TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) { data.reserve(128 * 1024); { - NoHeapChecker no_heap; + // TODO(teboring): Enable no heap check when ArenaStringPtr is used in map. + // NoHeapChecker no_heap; unittest::TestArenaMap* from = Arena::CreateMessage(&arena); @@ -2326,6 +2448,22 @@ TEST(ArenaTest, RelfectionInTextFormat) { MapTestUtil::ExpectArenaMapFieldsSet(*to); } +// Make sure the memory allocated for string in map is deallocated. +TEST(ArenaTest, StringMapNoLeak) { + Arena arena; + unittest::TestArenaMap* message = + Arena::CreateMessage(&arena); + string data; + // String with length less than 16 will not be allocated from heap. + int original_capacity = data.capacity(); + while (data.capacity() <= original_capacity) { + data.append("a"); + } + (*message->mutable_map_string_string())[data] = data; + // We rely on heap checkers to detect memory leak for us. + ASSERT_FALSE(message == NULL); +} + } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/map_test_util.cc b/src/google/protobuf/map_test_util.cc index 1713e373..ae094647 100644 --- a/src/google/protobuf/map_test_util.cc +++ b/src/google/protobuf/map_test_util.cc @@ -209,7 +209,7 @@ std::vector MapTestUtil::GetMapEntriesFromRelease( return result; } -MapTestUtil::MapReflectionTester::MapReflectionTester( +MapReflectionTester::MapReflectionTester( const Descriptor* base_descriptor) : base_descriptor_(base_descriptor) { const DescriptorPool* pool = base_descriptor->file()->pool(); @@ -329,14 +329,14 @@ MapTestUtil::MapReflectionTester::MapReflectionTester( } // Shorthand to get a FieldDescriptor for a field of unittest::TestMap. -const FieldDescriptor* MapTestUtil::MapReflectionTester::F(const string& name) { +const FieldDescriptor* MapReflectionTester::F(const string& name) { const FieldDescriptor* result = NULL; result = base_descriptor_->FindFieldByName(name); GOOGLE_CHECK(result != NULL); return result; } -void MapTestUtil::MapReflectionTester::SetMapFieldsViaReflection( +void MapReflectionTester::SetMapFieldsViaReflection( Message* message) { const Reflection* reflection = message->GetReflection(); Message* sub_message = NULL; @@ -555,7 +555,196 @@ void MapTestUtil::MapReflectionTester::SetMapFieldsViaReflection( SetInt32(sub_foreign_message, foreign_c_, 1); } -void MapTestUtil::MapReflectionTester::ClearMapFieldsViaReflection( +void MapReflectionTester::SetMapFieldsViaMapReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + + Message* sub_foreign_message = NULL; + MapValueRef map_val; + + // Add first element. + MapKey map_key; + map_key.SetInt32Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_int32_int32"), map_key, &map_val)); + map_val.SetInt32Value(0); + + map_key.SetInt64Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_int64_int64"), map_key, &map_val)); + map_val.SetInt64Value(0); + + map_key.SetUInt32Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_uint32_uint32"), map_key, &map_val)); + map_val.SetUInt32Value(0); + + map_key.SetUInt64Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_uint64_uint64"), map_key, &map_val)); + map_val.SetUInt64Value(0); + + map_key.SetInt32Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_sint32_sint32"), map_key, &map_val)); + map_val.SetInt32Value(0); + + map_key.SetInt64Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_sint64_sint64"), map_key, &map_val)); + map_val.SetInt64Value(0); + + map_key.SetUInt32Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_fixed32_fixed32"), map_key, &map_val)); + map_val.SetUInt32Value(0); + + map_key.SetUInt64Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_fixed64_fixed64"), map_key, &map_val)); + map_val.SetUInt64Value(0); + + map_key.SetInt32Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_sfixed32_sfixed32"), map_key, &map_val)); + map_val.SetInt32Value(0); + + map_key.SetInt64Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_sfixed64_sfixed64"), map_key, &map_val)); + map_val.SetInt64Value(0); + + map_key.SetInt32Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_int32_float"), map_key, &map_val)); + map_val.SetFloatValue(0.0); + + map_key.SetInt32Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_int32_double"), map_key, &map_val)); + map_val.SetDoubleValue(0.0); + + map_key.SetBoolValue(false); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_bool_bool"), map_key, &map_val)); + map_val.SetBoolValue(false); + + map_key.SetStringValue("0"); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_string_string"), map_key, &map_val)); + map_val.SetStringValue("0"); + + map_key.SetInt32Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_int32_bytes"), map_key, &map_val)); + map_val.SetStringValue("0"); + + map_key.SetInt32Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_int32_enum"), map_key, &map_val)); + map_val.SetEnumValue(map_enum_bar_->number()); + + map_key.SetInt32Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_int32_foreign_message"), map_key, &map_val)); + sub_foreign_message = map_val.MutableMessageValue(); + sub_foreign_message->GetReflection()->SetInt32( + sub_foreign_message, foreign_c_, 0); + + // Add second element + map_key.SetInt32Value(1); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_int32_int32"), map_key, &map_val)); + map_val.SetInt32Value(1); + EXPECT_FALSE(reflection->InsertOrLookupMapValue( + message, F("map_int32_int32"), map_key, &map_val)); + + map_key.SetInt64Value(1); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_int64_int64"), map_key, &map_val)); + map_val.SetInt64Value(1); + EXPECT_FALSE(reflection->InsertOrLookupMapValue( + message, F("map_int64_int64"), map_key, &map_val)); + + map_key.SetUInt32Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_uint32_uint32"), map_key, &map_val); + map_val.SetUInt32Value(1); + + map_key.SetUInt64Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_uint64_uint64"), map_key, &map_val); + map_val.SetUInt64Value(1); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_sint32_sint32"), map_key, &map_val); + map_val.SetInt32Value(1); + + map_key.SetInt64Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_sint64_sint64"), map_key, &map_val); + map_val.SetInt64Value(1); + + map_key.SetUInt32Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_fixed32_fixed32"), map_key, &map_val); + map_val.SetUInt32Value(1); + + map_key.SetUInt64Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_fixed64_fixed64"), map_key, &map_val); + map_val.SetUInt64Value(1); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_sfixed32_sfixed32"), map_key, &map_val); + map_val.SetInt32Value(1); + + map_key.SetInt64Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_sfixed64_sfixed64"), map_key, &map_val); + map_val.SetInt64Value(1); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_int32_float"), map_key, &map_val); + map_val.SetFloatValue(1.0); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_int32_double"), map_key, &map_val); + map_val.SetDoubleValue(1.0); + + map_key.SetBoolValue(true); + reflection->InsertOrLookupMapValue( + message, F("map_bool_bool"), map_key, &map_val); + map_val.SetBoolValue(true); + + map_key.SetStringValue("1"); + reflection->InsertOrLookupMapValue( + message, F("map_string_string"), map_key, &map_val); + map_val.SetStringValue("1"); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_int32_bytes"), map_key, &map_val); + map_val.SetStringValue("1"); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_int32_enum"), map_key, &map_val); + map_val.SetEnumValue(map_enum_baz_->number()); + + map_key.SetInt32Value(1); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_int32_foreign_message"), map_key, &map_val)); + sub_foreign_message = map_val.MutableMessageValue(); + sub_foreign_message->GetReflection()->SetInt32( + sub_foreign_message, foreign_c_, 1); +} + +void MapReflectionTester::ClearMapFieldsViaReflection( Message* message) { const Reflection* reflection = message->GetReflection(); @@ -578,97 +767,103 @@ void MapTestUtil::MapReflectionTester::ClearMapFieldsViaReflection( reflection->ClearField(message, F("map_int32_foreign_message")); } -void MapTestUtil::MapReflectionTester::ModifyMapFieldsViaReflection( +void MapReflectionTester::ModifyMapFieldsViaReflection( Message* message) { const Reflection* reflection = message->GetReflection(); - Message* sub_message; + MapValueRef map_val; Message* sub_foreign_message; - // Find out which one's key is 0. - int size = reflection->FieldSize(*message, F("map_int32_int32")); - int target = 0; - for (int i = 0; i < size; i++) { - const Message& temp_message = reflection - ->GetRepeatedMessage(*message, F("map_int32_int32"), i); - if (temp_message.GetReflection() - ->GetInt32(temp_message, map_int32_int32_key_) == 1) { - target = i; - } - } - - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_int32_int32"), target); - sub_message->GetReflection() - ->SetInt32(sub_message, map_int32_int32_val_, 2); - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_int64_int64"), target); - sub_message->GetReflection() - ->SetInt64(sub_message, map_int64_int64_val_, 2); - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_uint32_uint32"), target); - sub_message->GetReflection() - ->SetUInt32(sub_message, map_uint32_uint32_val_, 2); - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_uint64_uint64"), target); - sub_message->GetReflection() - ->SetUInt64(sub_message, map_uint64_uint64_val_, 2); - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_sint32_sint32"), target); - sub_message->GetReflection() - ->SetInt32(sub_message, map_sint32_sint32_val_, 2); - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_sint64_sint64"), target); - sub_message->GetReflection() - ->SetInt64(sub_message, map_sint64_sint64_val_, 2); - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_fixed32_fixed32"), target); - sub_message->GetReflection() - ->SetUInt32(sub_message, map_fixed32_fixed32_val_, 2); - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_fixed64_fixed64"), target); - sub_message->GetReflection() - ->SetUInt64(sub_message, map_fixed64_fixed64_val_, 2); - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_sfixed32_sfixed32"), target); - sub_message->GetReflection() - ->SetInt32(sub_message, map_sfixed32_sfixed32_val_, 2); - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_sfixed64_sfixed64"), target); - sub_message->GetReflection() - ->SetInt64(sub_message, map_sfixed64_sfixed64_val_, 2); - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_int32_float"), target); - sub_message->GetReflection() - ->SetFloat(sub_message, map_int32_float_val_, 2.0); - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_int32_double"), target); - sub_message->GetReflection() - ->SetDouble(sub_message, map_int32_double_val_, 2.0); - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_bool_bool"), target); - sub_message->GetReflection() - ->SetBool(sub_message, map_bool_bool_val_, false); - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_string_string"), target); - sub_message->GetReflection() - ->SetString(sub_message, map_string_string_val_, "2"); - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_int32_bytes"), target); - sub_message->GetReflection() - ->SetString(sub_message, map_int32_bytes_val_, "2"); - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_int32_enum"), target); - sub_message->GetReflection() - ->SetEnum(sub_message, map_int32_enum_val_, map_enum_foo_); - sub_message = reflection - ->MutableRepeatedMessage(message, F("map_int32_foreign_message"), target); - sub_foreign_message = sub_message->GetReflection()-> - MutableMessage(sub_message, map_int32_foreign_message_val_, NULL); - sub_foreign_message->GetReflection()-> - SetInt32(sub_foreign_message, foreign_c_, 2); + // Modify the second element + MapKey map_key; + map_key.SetInt32Value(1); + EXPECT_FALSE(reflection->InsertOrLookupMapValue( + message, F("map_int32_int32"), map_key, &map_val)); + map_val.SetInt32Value(2); + + map_key.SetInt64Value(1); + EXPECT_FALSE(reflection->InsertOrLookupMapValue( + message, F("map_int64_int64"), map_key, &map_val)); + map_val.SetInt64Value(2); + + map_key.SetUInt32Value(1); + EXPECT_FALSE(reflection->InsertOrLookupMapValue( + message, F("map_uint32_uint32"), map_key, &map_val)); + map_val.SetUInt32Value(2); + + map_key.SetUInt64Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_uint64_uint64"), map_key, &map_val); + map_val.SetUInt64Value(2); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_sint32_sint32"), map_key, &map_val); + map_val.SetInt32Value(2); + + map_key.SetInt64Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_sint64_sint64"), map_key, &map_val); + map_val.SetInt64Value(2); + + map_key.SetUInt32Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_fixed32_fixed32"), map_key, &map_val); + map_val.SetUInt32Value(2); + + map_key.SetUInt64Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_fixed64_fixed64"), map_key, &map_val); + map_val.SetUInt64Value(2); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_sfixed32_sfixed32"), map_key, &map_val); + map_val.SetInt32Value(2); + + map_key.SetInt64Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_sfixed64_sfixed64"), map_key, &map_val); + map_val.SetInt64Value(2); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_int32_float"), map_key, &map_val); + map_val.SetFloatValue(2.0); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_int32_double"), map_key, &map_val); + map_val.SetDoubleValue(2.0); + + map_key.SetBoolValue(true); + reflection->InsertOrLookupMapValue( + message, F("map_bool_bool"), map_key, &map_val); + map_val.SetBoolValue(false); + + map_key.SetStringValue("1"); + reflection->InsertOrLookupMapValue( + message, F("map_string_string"), map_key, &map_val); + map_val.SetStringValue("2"); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_int32_bytes"), map_key, &map_val); + map_val.SetStringValue("2"); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue( + message, F("map_int32_enum"), map_key, &map_val); + map_val.SetEnumValue(map_enum_foo_->number()); + + map_key.SetInt32Value(1); + EXPECT_FALSE(reflection->InsertOrLookupMapValue( + message, F("map_int32_foreign_message"), map_key, &map_val)); + sub_foreign_message = map_val.MutableMessageValue(); + sub_foreign_message->GetReflection()->SetInt32( + sub_foreign_message, foreign_c_, 2); } -void MapTestUtil::MapReflectionTester::RemoveLastMapsViaReflection( +void MapReflectionTester::RemoveLastMapsViaReflection( Message* message) { const Reflection* reflection = message->GetReflection(); @@ -681,7 +876,7 @@ void MapTestUtil::MapReflectionTester::RemoveLastMapsViaReflection( } } -void MapTestUtil::MapReflectionTester::ReleaseLastMapsViaReflection( +void MapReflectionTester::ReleaseLastMapsViaReflection( Message* message) { const Reflection* reflection = message->GetReflection(); @@ -699,7 +894,7 @@ void MapTestUtil::MapReflectionTester::ReleaseLastMapsViaReflection( } } -void MapTestUtil::MapReflectionTester::SwapMapsViaReflection(Message* message) { +void MapReflectionTester::SwapMapsViaReflection(Message* message) { const Reflection* reflection = message->GetReflection(); vector output; reflection->ListFields(*message, &output); @@ -710,7 +905,7 @@ void MapTestUtil::MapReflectionTester::SwapMapsViaReflection(Message* message) { } } -void MapTestUtil::MapReflectionTester:: +void MapReflectionTester:: MutableUnknownFieldsOfMapFieldsViaReflection(Message* message) { const Reflection* reflection = message->GetReflection(); Message* sub_message = NULL; @@ -768,11 +963,12 @@ void MapTestUtil::MapReflectionTester:: NULL); } -void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( +void MapReflectionTester::ExpectMapFieldsSetViaReflection( const Message& message) { string scratch; const Reflection* reflection = message.GetReflection(); const Message* sub_message; + MapKey map_key; // ----------------------------------------------------------------- @@ -799,6 +995,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( map[0] = 0; map[1] = 1; for (int i = 0; i < 2; i++) { + // Check with RepeatedField Reflection sub_message = &reflection->GetRepeatedMessage(message, F("map_int32_int32"), i); int32 key = sub_message->GetReflection()->GetInt32( @@ -806,6 +1003,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( int32 val = sub_message->GetReflection()->GetInt32( *sub_message, map_int32_int32_val_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt32Value(key); + EXPECT_TRUE(reflection->ContainsMapKey( + message, F("map_int32_int32"), map_key)); } } { @@ -813,6 +1014,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( map[0] = 0; map[1] = 1; for (int i = 0; i < 2; i++) { + // Check with RepeatedField Reflection sub_message = &reflection->GetRepeatedMessage(message, F("map_int64_int64"), i); int64 key = sub_message->GetReflection()->GetInt64( @@ -820,6 +1022,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( int64 val = sub_message->GetReflection()->GetInt64( *sub_message, map_int64_int64_val_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt64Value(key); + EXPECT_TRUE(reflection->ContainsMapKey( + message, F("map_int64_int64"), map_key)); } } { @@ -827,6 +1033,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( map[0] = 0; map[1] = 1; for (int i = 0; i < 2; i++) { + // Check with RepeatedField Reflection sub_message = &reflection->GetRepeatedMessage(message, F("map_uint32_uint32"), i); uint32 key = sub_message->GetReflection()->GetUInt32( @@ -834,6 +1041,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( uint32 val = sub_message->GetReflection()->GetUInt32( *sub_message, map_uint32_uint32_val_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetUInt32Value(key); + EXPECT_TRUE(reflection->ContainsMapKey( + message, F("map_uint32_uint32"), map_key)); } } { @@ -848,6 +1059,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( uint64 val = sub_message->GetReflection()->GetUInt64( *sub_message, map_uint64_uint64_val_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetUInt64Value(key); + EXPECT_TRUE(reflection->ContainsMapKey( + message, F("map_uint64_uint64"), map_key)); } } { @@ -862,6 +1077,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( int32 val = sub_message->GetReflection()->GetInt32( *sub_message, map_sint32_sint32_val_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt32Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_sint32_sint32"), map_key)); } } { @@ -876,6 +1095,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( int64 val = sub_message->GetReflection()->GetInt64( *sub_message, map_sint64_sint64_val_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt64Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_sint64_sint64"), map_key)); } } { @@ -890,6 +1113,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( uint32 val = sub_message->GetReflection()->GetUInt32( *sub_message, map_fixed32_fixed32_val_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetUInt32Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_fixed32_fixed32"), map_key)); } } { @@ -904,6 +1131,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( uint64 val = sub_message->GetReflection()->GetUInt64( *sub_message, map_fixed64_fixed64_val_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetUInt64Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_fixed64_fixed64"), map_key)); } } { @@ -918,6 +1149,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( int32 val = sub_message->GetReflection()->GetInt32( *sub_message, map_sfixed32_sfixed32_val_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt32Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_sfixed32_sfixed32"), map_key)); } } { @@ -932,6 +1167,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( int64 val = sub_message->GetReflection()->GetInt64( *sub_message, map_sfixed64_sfixed64_val_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt64Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_sfixed64_sfixed64"), map_key)); } } { @@ -946,6 +1185,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( float val = sub_message->GetReflection()->GetFloat( *sub_message, map_int32_float_val_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt32Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_int32_float"), map_key)); } } { @@ -960,6 +1203,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( double val = sub_message->GetReflection()->GetDouble( *sub_message, map_int32_double_val_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt32Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_int32_double"), map_key)); } } { @@ -974,6 +1221,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( bool val = sub_message->GetReflection()->GetBool( *sub_message, map_bool_bool_val_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetBoolValue(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_bool_bool"), map_key)); } } { @@ -988,6 +1239,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( string val = sub_message->GetReflection()->GetString( *sub_message, map_string_string_val_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetStringValue(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_string_string"), map_key)); } } { @@ -1002,6 +1257,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( string val = sub_message->GetReflection()->GetString( *sub_message, map_int32_bytes_val_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt32Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_int32_bytes"), map_key)); } } { @@ -1016,6 +1275,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( const EnumValueDescriptor* val = sub_message->GetReflection()->GetEnum( *sub_message, map_int32_enum_val_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt32Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_int32_enum"), map_key)); } } { @@ -1032,11 +1295,245 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( int32 val = foreign_message.GetReflection()->GetInt32( foreign_message, foreign_c_); EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt32Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_int32_foreign_message"), map_key)); } } } -void MapTestUtil::MapReflectionTester::ExpectClearViaReflection( +void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( + Message* message) { + string scratch; + string serialized; + const Reflection* reflection = message->GetReflection(); + + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_int32"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int64_int64"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_uint32_uint32"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_uint64_uint64"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sint32_sint32"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sint64_sint64"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_fixed32_fixed32"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_fixed64_fixed64"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sfixed32_sfixed32"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sfixed64_sfixed64"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_float"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_double"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_bool_bool"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_string_string"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_bytes"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_enum"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_foreign_message"))); + + { + std::map map; + map[0] = 0; + map[1] = 1; + int size = 0; + for (MapIterator iter = reflection->MapBegin(message, F("map_int32_int32")); + iter != reflection->MapEnd(message, F("map_int32_int32")); + ++iter, ++size) { + // Check const methods do not invalidate map. + message->DebugString(); + message->ShortDebugString(); + message->SerializeToString(&serialized); + message->SpaceUsed(); + message->ByteSize(); + EXPECT_EQ(map[iter.GetKey().GetInt32Value()], + iter.GetValueRef().GetInt32Value()); + } + EXPECT_EQ(size, 2); + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (MapIterator iter = reflection->MapBegin(message, F("map_int64_int64")); + iter != reflection->MapEnd(message, F("map_int64_int64")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetInt64Value()], + iter.GetValueRef().GetInt64Value()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (MapIterator iter = reflection->MapBegin( + message, F("map_uint32_uint32")); + iter != reflection->MapEnd(message, F("map_uint32_uint32")); + ++iter) { + EXPECT_EQ(map[iter.GetKey().GetUInt32Value()], + iter.GetValueRef().GetUInt32Value()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (MapIterator iter = reflection->MapBegin( + message, F("map_uint64_uint64")); + iter != reflection->MapEnd(message, F("map_uint64_uint64")); + ++iter) { + EXPECT_EQ(map[iter.GetKey().GetUInt64Value()], + iter.GetValueRef().GetUInt64Value()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (MapIterator iter = reflection->MapBegin( + message, F("map_sint32_sint32")); + iter != reflection->MapEnd(message, F("map_sint32_sint32")); + ++iter) { + EXPECT_EQ(map[iter.GetKey().GetInt32Value()], + iter.GetValueRef().GetInt32Value()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (MapIterator iter = reflection->MapBegin( + message, F("map_sint64_sint64")); + iter != reflection->MapEnd(message, F("map_sint64_sint64")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetInt64Value()], + iter.GetValueRef().GetInt64Value()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (MapIterator iter = reflection->MapBegin( + message, F("map_fixed32_fixed32")); + iter != reflection->MapEnd(message, F("map_fixed32_fixed32")); + ++iter) { + EXPECT_EQ(map[iter.GetKey().GetUInt32Value()], + iter.GetValueRef().GetUInt32Value()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (MapIterator iter = reflection->MapBegin( + message, F("map_fixed64_fixed64")); + iter != reflection->MapEnd(message, F("map_fixed64_fixed64")); + ++iter) { + EXPECT_EQ(map[iter.GetKey().GetUInt64Value()], + iter.GetValueRef().GetUInt64Value()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (MapIterator iter = reflection->MapBegin( + message, F("map_sfixed32_sfixed32")); + iter != reflection->MapEnd(message, F("map_sfixed32_sfixed32")); + ++iter) { + EXPECT_EQ(map[iter.GetKey().GetInt32Value()], + iter.GetValueRef().GetInt32Value()); + } + } + { + std::map map; + map[0] = 0.0; + map[1] = 1.0; + for (MapIterator iter = reflection->MapBegin(message, F("map_int32_float")); + iter != reflection->MapEnd(message, F("map_int32_float")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetInt32Value()], + iter.GetValueRef().GetFloatValue()); + } + } + { + std::map map; + map[0] = 0.0; + map[1] = 1.0; + for (MapIterator iter = reflection->MapBegin( + message, F("map_int32_double")); + iter != reflection->MapEnd(message, F("map_int32_double")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetInt32Value()], + iter.GetValueRef().GetDoubleValue()); + } + } + { + std::map map; + map[false] = false; + map[true] = true; + for (MapIterator iter = reflection->MapBegin(message, F("map_bool_bool")); + iter != reflection->MapEnd(message, F("map_bool_bool")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetBoolValue()], + iter.GetValueRef().GetBoolValue()); + } + } + { + std::map map; + map["0"] = "0"; + map["1"] = "1"; + int size = 0; + for (MapIterator iter = reflection->MapBegin( + message, F("map_string_string")); + iter != reflection->MapEnd(message, F("map_string_string")); + ++iter, ++size) { + // Check const methods do not invalidate map. + message->DebugString(); + message->ShortDebugString(); + message->SerializeToString(&serialized); + message->SpaceUsed(); + message->ByteSize(); + EXPECT_EQ(map[iter.GetKey().GetStringValue()], + iter.GetValueRef().GetStringValue()); + } + EXPECT_EQ(size, 2); + } + { + std::map map; + map[0] = "0"; + map[1] = "1"; + for (MapIterator iter = reflection->MapBegin(message, F("map_int32_bytes")); + iter != reflection->MapEnd(message, F("map_int32_bytes")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetInt32Value()], + iter.GetValueRef().GetStringValue()); + } + } + { + std::map map; + map[0] = map_enum_bar_; + map[1] = map_enum_baz_; + for (MapIterator iter = reflection->MapBegin(message, F("map_int32_enum")); + iter != reflection->MapEnd(message, F("map_int32_enum")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetInt32Value()]->number(), + iter.GetValueRef().GetEnumValue()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + int size = 0; + for (MapIterator iter = reflection->MapBegin( + message, F("map_int32_foreign_message")); + iter != reflection->MapEnd(message, F("map_int32_foreign_message")); + ++iter, ++size) { + // Check const methods do not invalidate map. + message->DebugString(); + message->ShortDebugString(); + message->SerializeToString(&serialized); + message->SpaceUsed(); + message->ByteSize(); + const Message& sub_message = iter.GetValueRef().GetMessageValue(); + EXPECT_EQ(map[iter.GetKey().GetInt32Value()], + sub_message.GetReflection()->GetInt32(sub_message, foreign_c_)); + } + EXPECT_EQ(size, 2); + } +} + +void MapReflectionTester::ExpectClearViaReflection( const Message& message) { const Reflection* reflection = message.GetReflection(); // Map fields are empty. @@ -1059,7 +1556,46 @@ void MapTestUtil::MapReflectionTester::ExpectClearViaReflection( EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_foreign_message"))); } -void MapTestUtil::MapReflectionTester::ExpectMapEntryClearViaReflection( +void MapReflectionTester::ExpectClearViaReflectionIterator( + Message* message) { + const Reflection* reflection = message->GetReflection(); + EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_int32")) == + reflection->MapEnd(message, F("map_int32_int32"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_int64_int64")) == + reflection->MapEnd(message, F("map_int64_int64"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_uint32_uint32")) == + reflection->MapEnd(message, F("map_uint32_uint32"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_uint64_uint64")) == + reflection->MapEnd(message, F("map_uint64_uint64"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_sint32_sint32")) == + reflection->MapEnd(message, F("map_sint32_sint32"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_sint64_sint64")) == + reflection->MapEnd(message, F("map_sint64_sint64"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_fixed32_fixed32")) == + reflection->MapEnd(message, F("map_fixed32_fixed32"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_fixed64_fixed64")) == + reflection->MapEnd(message, F("map_fixed64_fixed64"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_sfixed32_sfixed32")) == + reflection->MapEnd(message, F("map_sfixed32_sfixed32"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_sfixed64_sfixed64")) == + reflection->MapEnd(message, F("map_sfixed64_sfixed64"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_float")) == + reflection->MapEnd(message, F("map_int32_float"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_double")) == + reflection->MapEnd(message, F("map_int32_double"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_bool_bool")) == + reflection->MapEnd(message, F("map_bool_bool"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_string_string")) == + reflection->MapEnd(message, F("map_string_string"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_bytes")) == + reflection->MapEnd(message, F("map_int32_bytes"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_enum")) == + reflection->MapEnd(message, F("map_int32_enum"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_foreign_message")) == + reflection->MapEnd(message, F("map_int32_foreign_message"))); +} + +void MapReflectionTester::ExpectMapEntryClearViaReflection( Message* message) { const Reflection* reflection = message->GetReflection(); const Message* sub_message; diff --git a/src/google/protobuf/map_test_util.h b/src/google/protobuf/map_test_util.h index f437e33e..107a639d 100644 --- a/src/google/protobuf/map_test_util.h +++ b/src/google/protobuf/map_test_util.h @@ -83,71 +83,74 @@ class MapTestUtil { // Get pointers of map entries from release. static std::vector GetMapEntriesFromRelease( unittest::TestMap* message); +}; - // Like above, but use the reflection interface. - class MapReflectionTester { - public: - // base_descriptor must be a descriptor for TestMap, which is used for - // MapReflectionTester to fetch the FieldDescriptors needed to use the - // reflection interface. - explicit MapReflectionTester(const Descriptor* base_descriptor); - - void SetMapFieldsViaReflection(Message* message); - void ClearMapFieldsViaReflection(Message* message); - void ModifyMapFieldsViaReflection(Message* message); - void RemoveLastMapsViaReflection(Message* message); - void ReleaseLastMapsViaReflection(Message* message); - void SwapMapsViaReflection(Message* message); - void MutableUnknownFieldsOfMapFieldsViaReflection(Message* message); - void ExpectMapFieldsSetViaReflection(const Message& message); - void ExpectClearViaReflection(const Message& message); - void ExpectMapEntryClearViaReflection(Message* message); - - private: - const FieldDescriptor* F(const string& name); - - const Descriptor* base_descriptor_; - - const EnumValueDescriptor* map_enum_bar_; - const EnumValueDescriptor* map_enum_baz_; - const EnumValueDescriptor* map_enum_foo_; - - const FieldDescriptor* foreign_c_; - const FieldDescriptor* map_int32_int32_key_; - const FieldDescriptor* map_int32_int32_val_; - const FieldDescriptor* map_int64_int64_key_; - const FieldDescriptor* map_int64_int64_val_; - const FieldDescriptor* map_uint32_uint32_key_; - const FieldDescriptor* map_uint32_uint32_val_; - const FieldDescriptor* map_uint64_uint64_key_; - const FieldDescriptor* map_uint64_uint64_val_; - const FieldDescriptor* map_sint32_sint32_key_; - const FieldDescriptor* map_sint32_sint32_val_; - const FieldDescriptor* map_sint64_sint64_key_; - const FieldDescriptor* map_sint64_sint64_val_; - const FieldDescriptor* map_fixed32_fixed32_key_; - const FieldDescriptor* map_fixed32_fixed32_val_; - const FieldDescriptor* map_fixed64_fixed64_key_; - const FieldDescriptor* map_fixed64_fixed64_val_; - const FieldDescriptor* map_sfixed32_sfixed32_key_; - const FieldDescriptor* map_sfixed32_sfixed32_val_; - const FieldDescriptor* map_sfixed64_sfixed64_key_; - const FieldDescriptor* map_sfixed64_sfixed64_val_; - const FieldDescriptor* map_int32_float_key_; - const FieldDescriptor* map_int32_float_val_; - const FieldDescriptor* map_int32_double_key_; - const FieldDescriptor* map_int32_double_val_; - const FieldDescriptor* map_bool_bool_key_; - const FieldDescriptor* map_bool_bool_val_; - const FieldDescriptor* map_string_string_key_; - const FieldDescriptor* map_string_string_val_; - const FieldDescriptor* map_int32_bytes_key_; - const FieldDescriptor* map_int32_bytes_val_; - const FieldDescriptor* map_int32_enum_key_; - const FieldDescriptor* map_int32_enum_val_; - const FieldDescriptor* map_int32_foreign_message_key_; - const FieldDescriptor* map_int32_foreign_message_val_; - }; +// Like above, but use the reflection interface. +class MapReflectionTester { + public: + // base_descriptor must be a descriptor for TestMap, which is used for + // MapReflectionTester to fetch the FieldDescriptors needed to use the + // reflection interface. + explicit MapReflectionTester(const Descriptor* base_descriptor); + + void SetMapFieldsViaReflection(Message* message); + void SetMapFieldsViaMapReflection(Message* message); + void ClearMapFieldsViaReflection(Message* message); + void ModifyMapFieldsViaReflection(Message* message); + void RemoveLastMapsViaReflection(Message* message); + void ReleaseLastMapsViaReflection(Message* message); + void SwapMapsViaReflection(Message* message); + void MutableUnknownFieldsOfMapFieldsViaReflection(Message* message); + void ExpectMapFieldsSetViaReflection(const Message& message); + void ExpectMapFieldsSetViaReflectionIterator(Message* message); + void ExpectClearViaReflection(const Message& message); + void ExpectClearViaReflectionIterator(Message* message); + void ExpectMapEntryClearViaReflection(Message* message); + + private: + const FieldDescriptor* F(const string& name); + + const Descriptor* base_descriptor_; + + const EnumValueDescriptor* map_enum_bar_; + const EnumValueDescriptor* map_enum_baz_; + const EnumValueDescriptor* map_enum_foo_; + + const FieldDescriptor* foreign_c_; + const FieldDescriptor* map_int32_int32_key_; + const FieldDescriptor* map_int32_int32_val_; + const FieldDescriptor* map_int64_int64_key_; + const FieldDescriptor* map_int64_int64_val_; + const FieldDescriptor* map_uint32_uint32_key_; + const FieldDescriptor* map_uint32_uint32_val_; + const FieldDescriptor* map_uint64_uint64_key_; + const FieldDescriptor* map_uint64_uint64_val_; + const FieldDescriptor* map_sint32_sint32_key_; + const FieldDescriptor* map_sint32_sint32_val_; + const FieldDescriptor* map_sint64_sint64_key_; + const FieldDescriptor* map_sint64_sint64_val_; + const FieldDescriptor* map_fixed32_fixed32_key_; + const FieldDescriptor* map_fixed32_fixed32_val_; + const FieldDescriptor* map_fixed64_fixed64_key_; + const FieldDescriptor* map_fixed64_fixed64_val_; + const FieldDescriptor* map_sfixed32_sfixed32_key_; + const FieldDescriptor* map_sfixed32_sfixed32_val_; + const FieldDescriptor* map_sfixed64_sfixed64_key_; + const FieldDescriptor* map_sfixed64_sfixed64_val_; + const FieldDescriptor* map_int32_float_key_; + const FieldDescriptor* map_int32_float_val_; + const FieldDescriptor* map_int32_double_key_; + const FieldDescriptor* map_int32_double_val_; + const FieldDescriptor* map_bool_bool_key_; + const FieldDescriptor* map_bool_bool_val_; + const FieldDescriptor* map_string_string_key_; + const FieldDescriptor* map_string_string_val_; + const FieldDescriptor* map_int32_bytes_key_; + const FieldDescriptor* map_int32_bytes_val_; + const FieldDescriptor* map_int32_enum_key_; + const FieldDescriptor* map_int32_enum_val_; + const FieldDescriptor* map_int32_foreign_message_key_; + const FieldDescriptor* map_int32_foreign_message_val_; }; } // namespace protobuf diff --git a/src/google/protobuf/map_test_util_impl.h b/src/google/protobuf/map_test_util_impl.h index 5e7882a1..7e8757ed 100644 --- a/src/google/protobuf/map_test_util_impl.h +++ b/src/google/protobuf/map_test_util_impl.h @@ -31,6 +31,7 @@ #ifndef GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__ #define GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__ +#include #include @@ -167,8 +168,11 @@ void MapTestUtilImpl::SetArenaMapFields(MapMessage* message) { (*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); + (*message->mutable_map_int32_foreign_message_no_arena())[0].set_c(0); // Add second element (*message->mutable_map_int32_int32())[1] = 1; @@ -184,8 +188,11 @@ void MapTestUtilImpl::SetArenaMapFields(MapMessage* message) { (*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); + (*message->mutable_map_int32_foreign_message_no_arena())[1].set_c(1); } template @@ -329,8 +336,11 @@ void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) { 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(2, message.map_int32_foreign_message_no_arena().size()); EXPECT_EQ(0, message.map_int32_int32().at(0)); EXPECT_EQ(0, message.map_int64_int64().at(0)); @@ -345,8 +355,11 @@ void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) { 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(0, message.map_int32_foreign_message_no_arena().at(0).c()); EXPECT_EQ(1, message.map_int32_int32().at(1)); EXPECT_EQ(1, message.map_int64_int64().at(1)); @@ -361,8 +374,11 @@ void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) { 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()); + EXPECT_EQ(1, message.map_int32_foreign_message_no_arena().at(1).c()); } template diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h index ffdb6dfb..5040e605 100644 --- a/src/google/protobuf/map_type_handler.h +++ b/src/google/protobuf/map_type_handler.h @@ -54,22 +54,6 @@ struct MapIf { typedef FalseType type; }; -// In MapField, string and message are stored as pointer while others are stored -// as object. However, google::protobuf::Map has unified api. Functions in this class -// convert key/value to type wanted in api regardless how it's stored -// internally. -template -class MapCommonTypeHandler { - public: - static inline Type& Reference(Type* x) { return *x; } - static inline Type& Reference(Type& x) { return x; } - static inline const Type& Reference(const Type& x) { return x; } - static inline Type* Pointer(Type* x) { return x; } - static inline Type* Pointer(Type& x) { return &x; } - static inline const Type* Pointer(const Type* x) { return x; } - static inline const Type* Pointer(const Type& x) { return &x; } -}; - // In proto2 Map, enum needs to be initialized to given default value, while // other types' default value can be inferred from the type. template @@ -110,174 +94,29 @@ template class MapArenaMessageCreator { public: static inline Type* CreateMessage(Arena* arena) { - return new Type; - } -}; - -// Handlers for key/value stored type in MapField. ================== - -// Handler for message -template -class MapCppTypeHandler : public MapCommonTypeHandler { - public: - static const bool kIsStringOrMessage = true; - // SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding - // those already calculate in sizeof(MapField). - static int SpaceUsedInMapEntry(const Type* value) { - return value->SpaceUsed(); - } - // 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)->Clear(); - } - static inline void ClearMaybeByDefaultEnum(Type** value, - int default_enum_value) { - if (*value != NULL) (*value)->Clear(); - } - static inline void Merge(const Type& from, Type** to) { - (*to)->MergeFrom(from); - } - - static void Delete(const Type* ptr) { delete ptr; } - - // Assign default value to given instance. - static inline void AssignDefaultValue(Type** value) { - *value = const_cast(&Type::default_instance()); - } - // Initialize value when constructing MapEntry - 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, Arena* arena) { - *x = NULL; - } - // Initialize value for the first time mutable accessor is called. - static inline void EnsureMutable(Type** value, Arena* arena) { - if (*value == NULL) { - *value = - MapArenaMessageCreator:: - type::value>::CreateMessage(arena); - } - } - // Return default instance if value is not initialized when calling const - // reference accessor. - 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. - static inline bool IsInitialized(Type* value) { - return value->IsInitialized(); - } -}; - -// Handler for string. -template <> -class MapCppTypeHandler : public MapCommonTypeHandler { - public: - static const bool kIsStringOrMessage = true; - static inline void Merge(const string& from, string** to) { **to = from; } - static inline void Clear(string** value) { (*value)->clear(); } - static inline void ClearMaybeByDefaultEnum(string** value, int default_enum) { - (*value)->clear(); - } - static inline int SpaceUsedInMapEntry(const string* value) { - return sizeof(*value) + StringSpaceUsedExcludingSelf(*value); - } - static inline int SpaceUsedInMap(const string& value) { - return sizeof(value) + StringSpaceUsedExcludingSelf(value); - } - static void Delete(const string* ptr) { - if (ptr != &::google::protobuf::internal::GetEmptyString()) delete ptr; - } - static inline void AssignDefaultValue(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, Arena* arena) { - *value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); - if (arena != NULL) arena->Own(*value); + return Arena::Create(arena); } - static inline void EnsureMutable(string** value, Arena* arena) { - if (*value == &::google::protobuf::internal::GetEmptyString()) { - *value = Arena::Create(arena); - } - } - 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; } }; -// Base class for primitive type handlers. -template -class MapPrimitiveTypeHandler : public MapCommonTypeHandler { - public: - static const bool kIsStringOrMessage = false; - static inline void Delete(const Type& x) {} - static inline void Merge(const Type& from, Type* to) { *to = from; } - static inline int SpaceUsedInMapEntry(const Type& value) { return 0; } - static inline int SpaceUsedInMap(const Type& value) { return sizeof(Type); } - static inline void AssignDefaultValue(Type* value) {} - static inline const Type& DefaultIfNotInitialized( - const Type& value, const Type& default_value) { - return value; - } - static inline bool IsInitialized(const Type& value) { return true; } -}; - -// Handlers for primitive types. -#define PRIMITIVE_HANDLER(CType) \ - template <> \ - class MapCppTypeHandler : public MapPrimitiveTypeHandler { \ - public: \ - static inline void Clear(CType* value) { *value = 0; } \ - static inline void ClearMaybeByDefaultEnum(CType* value, \ - int default_enum_value) { \ - *value = static_cast(default_enum_value); \ - } \ - static inline void Initialize(CType* value, Arena* arena) { *value = 0; } \ - static inline void InitializeMaybeByDefaultEnum(CType* value, \ - int default_enum_value, \ - Arena* arena) { \ - *value = static_cast(default_enum_value); \ - } \ - static inline void EnsureMutable(CType* value, Arena* arena) {} \ - }; - -PRIMITIVE_HANDLER(int32 ) -PRIMITIVE_HANDLER(int64 ) -PRIMITIVE_HANDLER(uint32) -PRIMITIVE_HANDLER(uint64) -PRIMITIVE_HANDLER(double) -PRIMITIVE_HANDLER(float ) -PRIMITIVE_HANDLER(bool ) - -#undef PRIMITIVE_HANDLER - // Define constants for given wire field type -template +template class MapWireFieldTypeTraits {}; -#define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \ - template <> \ - class MapWireFieldTypeTraits { \ - public: \ - typedef CType CppType; \ - static const bool kIsMessage = IsMessage; \ - static const bool kIsEnum = IsEnum; \ - static const WireFormatLite::WireType kWireType = \ - WireFormatLite::WIRETYPE_##WireFormatType; \ +#define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \ + template \ + class MapWireFieldTypeTraits { \ + public: \ + static const bool kIsMessage = IsMessage; \ + static const bool kIsEnum = IsEnum; \ + typedef typename MapIf::type TypeOnMemory; \ + typedef typename MapIf::type MapEntryAccessorType; \ + static const WireFormatLite::WireType kWireType = \ + WireFormatLite::WIRETYPE_##WireFormatType; \ }; -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(MESSAGE , Type, LENGTH_DELIMITED, true, false) +TYPE_TRAITS(STRING , ArenaStringPtr, LENGTH_DELIMITED, false, false) +TYPE_TRAITS(BYTES , ArenaStringPtr , LENGTH_DELIMITED, false, false) TYPE_TRAITS(INT64 , int64 , VARINT , false, false) TYPE_TRAITS(UINT64 , uint64 , VARINT , false, false) TYPE_TRAITS(INT32 , int32 , VARINT , false, false) @@ -295,46 +134,149 @@ TYPE_TRAITS(BOOL , bool , VARINT , false, false) #undef TYPE_TRAITS -template -class MapWireFieldTypeHandler { +template +class MapTypeHandler {}; + +template +class MapTypeHandler { public: + // Enum type cannot be used for MapTypeHandler::Read. Define a type which will + // replace Enum with int. + typedef typename MapWireFieldTypeTraits::MapEntryAccessorType MapEntryAccessorType; // Internal stored type in MapEntryLite for given wire field type. - typedef typename MapWireFieldTypeTraits::CppType CppType; + typedef typename MapWireFieldTypeTraits::TypeOnMemory TypeOnMemory; // Corresponding wire type for field type. static const WireFormatLite::WireType kWireType = - MapWireFieldTypeTraits::kWireType; + MapWireFieldTypeTraits::kWireType; // Whether wire type is for message. - static const bool kIsMessage = MapWireFieldTypeTraits::kIsMessage; + static const bool kIsMessage = + MapWireFieldTypeTraits::kIsMessage; // Whether wire type is for enum. - static const bool kIsEnum = MapWireFieldTypeTraits::kIsEnum; + static const bool kIsEnum = + MapWireFieldTypeTraits::kIsEnum; // Functions used in parsing and serialization. =================== - template - static inline int ByteSize(const ValueType& value); - template - static inline int GetCachedSize(const ValueType& value); - template - static inline bool Read(io::CodedInputStream* input, ValueType* value); - static inline void Write(int field, const CppType& value, + static inline int ByteSize(const MapEntryAccessorType& value); + static inline int GetCachedSize(const MapEntryAccessorType& value); + static inline bool Read(io::CodedInputStream* input, + MapEntryAccessorType* value); + static inline void Write(int field, const MapEntryAccessorType& value, io::CodedOutputStream* output); - static inline uint8* WriteToArray(int field, const CppType& value, + static inline uint8* WriteToArray(int field, + const MapEntryAccessorType& value, uint8* output); + + // Functions to manipulate data on memory. ======================== + static inline const Type& GetExternalReference(const Type* value); + static inline void DeleteNoArena(const Type* x); + static inline void Merge(const Type& from, Type** to, Arena* arena); + static inline void Clear(Type** value, Arena* arena); + static inline void ClearMaybeByDefaultEnum(Type** value, Arena* arena, + int default_enum_value); + static inline void Initialize(Type** x, Arena* arena); + + static inline void InitializeMaybeByDefaultEnum(Type** x, + int default_enum_value, + Arena* arena); + static inline Type* EnsureMutable(Type** value, Arena* arena); + // SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding + // those already calculate in sizeof(MapField). + static inline int SpaceUsedInMapEntry(const Type* value); + // Return bytes used by value in Map. + static inline int SpaceUsedInMap(const Type& value); + // Assign default value to given instance. + static inline void AssignDefaultValue(Type** value); + // Return default instance if value is not initialized when calling const + // reference accessor. + static inline const Type& DefaultIfNotInitialized( + const Type* value, const Type* default_value); + // Check if all required fields have values set. + static inline bool IsInitialized(Type* value); }; -template <> -template -inline int MapWireFieldTypeHandler::ByteSize( - const ValueType& value) { +#define MAP_HANDLER(FieldType) \ + template \ + class MapTypeHandler { \ + public: \ + typedef typename MapWireFieldTypeTraits::MapEntryAccessorType \ + MapEntryAccessorType; \ + typedef typename MapWireFieldTypeTraits::TypeOnMemory TypeOnMemory; \ + static const WireFormatLite::WireType kWireType = \ + MapWireFieldTypeTraits::kWireType; \ + static const bool kIsMessage = \ + MapWireFieldTypeTraits::kIsMessage; \ + static const bool kIsEnum = \ + MapWireFieldTypeTraits::kIsEnum; \ + static inline int ByteSize(const MapEntryAccessorType& value); \ + static inline int GetCachedSize(const MapEntryAccessorType& value); \ + static inline bool Read(io::CodedInputStream* input, \ + MapEntryAccessorType* value); \ + static inline void Write(int field, const MapEntryAccessorType& value, \ + io::CodedOutputStream* output); \ + static inline uint8* WriteToArray(int field, \ + const MapEntryAccessorType& value, \ + uint8* output); \ + static inline const MapEntryAccessorType& GetExternalReference( \ + const TypeOnMemory& value); \ + static inline void DeleteNoArena(const TypeOnMemory& x); \ + static inline void Merge(const MapEntryAccessorType& from, \ + TypeOnMemory* to, Arena* arena); \ + static inline void Clear(TypeOnMemory* value, Arena* arena); \ + static inline void ClearMaybeByDefaultEnum(TypeOnMemory* value, \ + Arena* arena, \ + int default_enum); \ + static inline int SpaceUsedInMapEntry(const TypeOnMemory& value); \ + static inline int SpaceUsedInMap(const TypeOnMemory& value); \ + static inline int SpaceUsedInMap(const string& value); \ + static inline void AssignDefaultValue(TypeOnMemory* value); \ + static inline const MapEntryAccessorType& DefaultIfNotInitialized( \ + const TypeOnMemory& value, const TypeOnMemory& default_value); \ + static inline bool IsInitialized(const TypeOnMemory& value); \ + static void DeleteNoArena(TypeOnMemory& value); \ + static inline void Initialize(TypeOnMemory* value, Arena* arena); \ + static inline void InitializeMaybeByDefaultEnum(TypeOnMemory* value, \ + int default_enum_value, \ + Arena* arena); \ + static inline MapEntryAccessorType* EnsureMutable(TypeOnMemory* value, \ + Arena* arena); \ + }; +MAP_HANDLER(STRING) +MAP_HANDLER(BYTES) +MAP_HANDLER(INT64) +MAP_HANDLER(UINT64) +MAP_HANDLER(INT32) +MAP_HANDLER(UINT32) +MAP_HANDLER(SINT64) +MAP_HANDLER(SINT32) +MAP_HANDLER(ENUM) +MAP_HANDLER(DOUBLE) +MAP_HANDLER(FLOAT) +MAP_HANDLER(FIXED64) +MAP_HANDLER(FIXED32) +MAP_HANDLER(SFIXED64) +MAP_HANDLER(SFIXED32) +MAP_HANDLER(BOOL) +#undef MAP_HANDLER + +template +inline int +MapTypeHandler::ByteSize( + const MapEntryAccessorType& value) { return WireFormatLite::MessageSizeNoVirtual(value); } -#define BYTE_SIZE(FieldType, DeclaredType) \ - template <> \ - template \ - inline int \ - MapWireFieldTypeHandler::ByteSize( \ - const ValueType& value) { \ - return WireFormatLite::DeclaredType##Size(value); \ +#define BYTE_SIZE(FieldType, DeclaredType) \ + template \ + inline int MapTypeHandler::ByteSize( \ + const MapEntryAccessorType& value) { \ + return WireFormatLite::DeclaredType##Size(value); \ } BYTE_SIZE(STRING, String) @@ -349,13 +291,11 @@ BYTE_SIZE(ENUM , Enum) #undef BYTE_SIZE -#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \ - template <> \ - template \ - inline int \ - MapWireFieldTypeHandler::ByteSize( \ - const ValueType& value) { \ - return WireFormatLite::k##DeclaredType##Size; \ +#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \ + template \ + inline int MapTypeHandler::ByteSize( \ + const MapEntryAccessorType& value) { \ + return WireFormatLite::k##DeclaredType##Size; \ } FIXED_BYTE_SIZE(DOUBLE , Double) @@ -368,20 +308,19 @@ FIXED_BYTE_SIZE(BOOL , Bool) #undef FIXED_BYTE_SIZE -template <> -template -inline int MapWireFieldTypeHandler< - WireFormatLite::TYPE_MESSAGE>::GetCachedSize(const ValueType& value) { +template +inline int +MapTypeHandler::GetCachedSize( + const MapEntryAccessorType& value) { return WireFormatLite::LengthDelimitedSize(value.GetCachedSize()); } -#define GET_CACHED_SIZE(FieldType, DeclaredType) \ - template <> \ - template \ - inline int \ - MapWireFieldTypeHandler::GetCachedSize( \ - const ValueType& value) { \ - return WireFormatLite::DeclaredType##Size(value); \ +#define GET_CACHED_SIZE(FieldType, DeclaredType) \ + template \ + inline int \ + MapTypeHandler::GetCachedSize( \ + const MapEntryAccessorType& value) { \ + return WireFormatLite::DeclaredType##Size(value); \ } GET_CACHED_SIZE(STRING, String) @@ -396,13 +335,12 @@ GET_CACHED_SIZE(ENUM , Enum) #undef GET_CACHED_SIZE -#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \ - template <> \ - template \ - inline int \ - MapWireFieldTypeHandler::GetCachedSize( \ - const ValueType& value) { \ - return WireFormatLite::k##DeclaredType##Size; \ +#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \ + template \ + inline int \ + MapTypeHandler::GetCachedSize( \ + const MapEntryAccessorType& value) { \ + return WireFormatLite::k##DeclaredType##Size; \ } GET_FIXED_CACHED_SIZE(DOUBLE , Double) @@ -415,30 +353,31 @@ GET_FIXED_CACHED_SIZE(BOOL , Bool) #undef GET_FIXED_CACHED_SIZE -template <> -inline void MapWireFieldTypeHandler::Write( - int field, const MessageLite& value, io::CodedOutputStream* output) { +template +inline void MapTypeHandler::Write( + int field, const MapEntryAccessorType& value, + io::CodedOutputStream* output) { WireFormatLite::WriteMessageMaybeToArray(field, value, output); } -template <> +template inline uint8* -MapWireFieldTypeHandler::WriteToArray( - int field, const MessageLite& value, uint8* output) { +MapTypeHandler::WriteToArray( + int field, const MapEntryAccessorType& value, uint8* output) { return WireFormatLite::WriteMessageToArray(field, value, output); } #define WRITE_METHOD(FieldType, DeclaredType) \ - template <> \ - inline void \ - MapWireFieldTypeHandler::Write( \ - int field, const CppType& value, io::CodedOutputStream* output) { \ + template \ + inline void MapTypeHandler::Write( \ + int field, const MapEntryAccessorType& value, \ + io::CodedOutputStream* output) { \ return WireFormatLite::Write##DeclaredType(field, value, output); \ } \ - template <> \ + template \ inline uint8* \ - MapWireFieldTypeHandler::WriteToArray( \ - int field, const CppType& value, uint8* output) { \ + MapTypeHandler::WriteToArray( \ + int field, const MapEntryAccessorType& value, uint8* output) { \ return WireFormatLite::Write##DeclaredType##ToArray(field, value, output); \ } @@ -461,35 +400,31 @@ WRITE_METHOD(BOOL , Bool) #undef WRITE_METHOD -template <> -template -inline bool MapWireFieldTypeHandler::Read( - io::CodedInputStream* input, ValueType* value) { +template +inline bool MapTypeHandler::Read( + io::CodedInputStream* input, MapEntryAccessorType* value) { return WireFormatLite::ReadMessageNoVirtual(input, value); } -template <> -template -inline bool MapWireFieldTypeHandler::Read( - io::CodedInputStream* input, ValueType* value) { +template +inline bool MapTypeHandler::Read( + io::CodedInputStream* input, MapEntryAccessorType* value) { return WireFormatLite::ReadString(input, value); } -template <> -template -inline bool MapWireFieldTypeHandler::Read( - io::CodedInputStream* input, ValueType* value) { +template +inline bool MapTypeHandler::Read( + io::CodedInputStream* input, MapEntryAccessorType* value) { return WireFormatLite::ReadBytes(input, value); } -#define READ_METHOD(FieldType) \ - template <> \ - template \ - inline bool MapWireFieldTypeHandler::Read( \ - io::CodedInputStream* input, ValueType* value) { \ - return WireFormatLite::ReadPrimitive( \ - input, value); \ +#define READ_METHOD(FieldType) \ + template \ + inline bool MapTypeHandler::Read( \ + io::CodedInputStream* input, MapEntryAccessorType* value) { \ + return WireFormatLite::ReadPrimitive( \ + input, value); \ } READ_METHOD(INT64) @@ -509,6 +444,282 @@ READ_METHOD(BOOL) #undef READ_METHOD +// Definition for message handler + +template +inline const Type& +MapTypeHandler::GetExternalReference(const Type* value) { + return *value; +} + +template +inline int +MapTypeHandler::SpaceUsedInMapEntry(const Type* value) { + return value->SpaceUsed(); +} + +template +int MapTypeHandler::SpaceUsedInMap( + const Type& value) { + return value.SpaceUsed(); +} + +template +inline void MapTypeHandler::Clear( + Type** value, Arena* arena) { + if (*value != NULL) (*value)->Clear(); +} +template +inline void +MapTypeHandler::ClearMaybeByDefaultEnum(Type** value, + Arena* arena, + int default_enum_value) { + if (*value != NULL) (*value)->Clear(); +} +template +inline void MapTypeHandler::Merge( + const Type& from, Type** to, Arena* arena) { + (*to)->MergeFrom(from); +} + +template +void MapTypeHandler::DeleteNoArena( + const Type* ptr) { + delete ptr; +} + +template +inline void MapTypeHandler::AssignDefaultValue(Type** value) { + *value = const_cast(&Type::default_instance()); +} + +template +inline void MapTypeHandler::Initialize(Type** x, + Arena* arena) { + *x = NULL; +} + +template +inline void MapTypeHandler:: + InitializeMaybeByDefaultEnum(Type** x, int default_enum_value, + Arena* arena) { + *x = NULL; +} + +template +inline Type* MapTypeHandler::EnsureMutable(Type** value, + Arena* arena) { + if (*value == NULL) { + *value = + MapArenaMessageCreator:: + type::value>::CreateMessage(arena); + } + return *value; +} + +template +inline const Type& MapTypeHandler:: + DefaultIfNotInitialized(const Type* value, const Type* default_value) { + return value != NULL ? *value : *default_value; +} + +template +inline bool MapTypeHandler::IsInitialized(Type* value) { + return value->IsInitialized(); +} + +// Definition for string/bytes handler + +#define STRING_OR_BYTES_HANDLER_FUNCTIONS(FieldType) \ + template \ + inline const typename MapTypeHandler::MapEntryAccessorType& \ + MapTypeHandler::GetExternalReference(const TypeOnMemory& value) { \ + return value.Get(&::google::protobuf::internal::GetEmptyString()); \ + } \ + template \ + inline int \ + MapTypeHandler::SpaceUsedInMapEntry( \ + const TypeOnMemory& value) { \ + return sizeof(value); \ + } \ + template \ + inline int MapTypeHandler::SpaceUsedInMap(const TypeOnMemory& value) { \ + return sizeof(value); \ + } \ + template \ + inline int MapTypeHandler::SpaceUsedInMap(const string& value) { \ + return sizeof(value); \ + } \ + template \ + inline void MapTypeHandler::Clear( \ + TypeOnMemory* value, Arena* arena) { \ + value->ClearToEmpty(&::google::protobuf::internal::GetEmptyString(), arena); \ + } \ + template \ + inline void \ + MapTypeHandler::ClearMaybeByDefaultEnum(TypeOnMemory* value, \ + Arena* arena, \ + int default_enum) { \ + Clear(value, arena); \ + } \ + template \ + inline void MapTypeHandler::Merge( \ + const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) { \ + to->Set(&::google::protobuf::internal::GetEmptyString(), from, arena); \ + } \ + template \ + void MapTypeHandler::DeleteNoArena( \ + TypeOnMemory& value) { \ + value.DestroyNoArena(&::google::protobuf::internal::GetEmptyString()); \ + } \ + template \ + inline void MapTypeHandler::AssignDefaultValue(TypeOnMemory* value) {} \ + template \ + inline void \ + MapTypeHandler::Initialize( \ + TypeOnMemory* value, Arena* arena) { \ + value->UnsafeSetDefault(&::google::protobuf::internal::GetEmptyString()); \ + } \ + template \ + inline void \ + MapTypeHandler::InitializeMaybeByDefaultEnum(TypeOnMemory* value, \ + int default_enum_value, \ + Arena* arena) { \ + Initialize(value, arena); \ + } \ + template \ + inline typename MapTypeHandler::MapEntryAccessorType* \ + MapTypeHandler::EnsureMutable( \ + TypeOnMemory* value, Arena* arena) { \ + return value->Mutable(&::google::protobuf::internal::GetEmptyString(), arena); \ + } \ + template \ + inline const typename MapTypeHandler::MapEntryAccessorType& \ + MapTypeHandler::DefaultIfNotInitialized(const TypeOnMemory& value, \ + const TypeOnMemory& \ + default_value) { \ + return value.Get(&::google::protobuf::internal::GetEmptyString()); \ + } \ + template \ + inline bool MapTypeHandler::IsInitialized(const TypeOnMemory& value) { \ + return true; \ + } +STRING_OR_BYTES_HANDLER_FUNCTIONS(STRING) +STRING_OR_BYTES_HANDLER_FUNCTIONS(BYTES) +#undef STRING_OR_BYTES_HANDLER_FUNCTIONS + +#define PRIMITIVE_HANDLER_FUNCTIONS(FieldType) \ + template \ + inline const typename MapTypeHandler::MapEntryAccessorType& \ + MapTypeHandler::GetExternalReference(const TypeOnMemory& value) { \ + return value; \ + } \ + template \ + inline int \ + MapTypeHandler::SpaceUsedInMapEntry( \ + const TypeOnMemory& value) { \ + return 0; \ + } \ + template \ + inline int MapTypeHandler::SpaceUsedInMap(const TypeOnMemory& value) { \ + return sizeof(Type); \ + } \ + template \ + inline void MapTypeHandler::Clear( \ + TypeOnMemory* value, Arena* arena) { \ + *value = 0; \ + } \ + template \ + inline void \ + MapTypeHandler::ClearMaybeByDefaultEnum(TypeOnMemory* value, \ + Arena* arena, \ + int default_enum_value) { \ + *value = static_cast(default_enum_value); \ + } \ + template \ + inline void MapTypeHandler::Merge( \ + const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) { \ + *to = from; \ + } \ + template \ + inline void MapTypeHandler::DeleteNoArena(TypeOnMemory& x) {} \ + template \ + inline void MapTypeHandler::AssignDefaultValue(TypeOnMemory* value) {} \ + template \ + inline void \ + MapTypeHandler::Initialize( \ + TypeOnMemory* value, Arena* arena) { \ + *value = 0; \ + } \ + template \ + inline void \ + MapTypeHandler::InitializeMaybeByDefaultEnum(TypeOnMemory* value, \ + int default_enum_value, \ + Arena* arena) { \ + *value = static_cast(default_enum_value); \ + } \ + template \ + inline typename MapTypeHandler::MapEntryAccessorType* \ + MapTypeHandler::EnsureMutable( \ + TypeOnMemory* value, Arena* arena) { \ + return value; \ + } \ + template \ + inline const typename MapTypeHandler::MapEntryAccessorType& \ + MapTypeHandler::DefaultIfNotInitialized(const TypeOnMemory& value, \ + const TypeOnMemory& \ + default_value) { \ + return value; \ + } \ + template \ + inline bool MapTypeHandler::IsInitialized(const TypeOnMemory& value) { \ + return true; \ + } +PRIMITIVE_HANDLER_FUNCTIONS(INT64) +PRIMITIVE_HANDLER_FUNCTIONS(UINT64) +PRIMITIVE_HANDLER_FUNCTIONS(INT32) +PRIMITIVE_HANDLER_FUNCTIONS(UINT32) +PRIMITIVE_HANDLER_FUNCTIONS(SINT64) +PRIMITIVE_HANDLER_FUNCTIONS(SINT32) +PRIMITIVE_HANDLER_FUNCTIONS(ENUM) +PRIMITIVE_HANDLER_FUNCTIONS(DOUBLE) +PRIMITIVE_HANDLER_FUNCTIONS(FLOAT) +PRIMITIVE_HANDLER_FUNCTIONS(FIXED64) +PRIMITIVE_HANDLER_FUNCTIONS(FIXED32) +PRIMITIVE_HANDLER_FUNCTIONS(SFIXED64) +PRIMITIVE_HANDLER_FUNCTIONS(SFIXED32) +PRIMITIVE_HANDLER_FUNCTIONS(BOOL) +#undef PRIMITIVE_HANDLER_FUNCTIONS + } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto index b308c7ff..d3b525a0 100644 --- a/src/google/protobuf/map_unittest.proto +++ b/src/google/protobuf/map_unittest.proto @@ -33,6 +33,7 @@ syntax = "proto3"; option cc_enable_arenas = true; import "google/protobuf/unittest.proto"; +import "google/protobuf/unittest_no_arena.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. @@ -58,6 +59,7 @@ message TestMap { map map_int32_bytes = 15; map map_int32_enum = 16; map map_int32_foreign_message = 17; + map map_string_foreign_message = 18; } message TestMapSubmessage { @@ -100,8 +102,12 @@ message TestArenaMap { map map_int32_float = 11; map map_int32_double = 12; map map_bool_bool = 13; - map map_int32_enum = 14; - map map_int32_foreign_message = 15; + map map_string_string = 14; + map map_int32_bytes = 15; + map map_int32_enum = 16; + map map_int32_foreign_message = 17; + map + map_int32_foreign_message_no_arena = 18; } // Previously, message containing enum called Type cannot be used as value of @@ -117,3 +123,7 @@ message MessageContainingEnumCalledType { message MessageContainingMapCalledEntry { map entry = 1; } + +message TestRecursiveMapMessage { + map a = 1; +} diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index 276d7de5..7d69c57a 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -38,12 +38,15 @@ #include +#include #include +#include #include #include #include #include #include +#include #include #include #include @@ -256,6 +259,22 @@ void Reflection::AddEnumValue(Message* message, GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API."; } +MapIterator Reflection::MapBegin( + Message* message, + const FieldDescriptor* field) const { + GOOGLE_LOG(FATAL) << "Unimplemented Map Reflection API."; + MapIterator iter(message, field); + return iter; +} + +MapIterator Reflection::MapEnd( + Message* message, + const FieldDescriptor* field) const { + GOOGLE_LOG(FATAL) << "Unimplemented Map Reflection API."; + MapIterator iter(message, field); + return iter; +} + // ============================================================================= // MessageFactory diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index 18c092d0..348e7c7f 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -134,12 +134,23 @@ class Reflection; class MessageFactory; // Defined in other files. +class MapKey; +class MapValueRef; +class MapIterator; +class MapReflectionTester; + +namespace internal { +class MapFieldBase; +} class UnknownFieldSet; // unknown_field_set.h namespace io { - class ZeroCopyInputStream; // zero_copy_stream.h - class ZeroCopyOutputStream; // zero_copy_stream.h - class CodedInputStream; // coded_stream.h - class CodedOutputStream; // coded_stream.h +class ZeroCopyInputStream; // zero_copy_stream.h +class ZeroCopyOutputStream; // zero_copy_stream.h +class CodedInputStream; // coded_stream.h +class CodedOutputStream; // coded_stream.h +} +namespace python { +class MapReflectionFriend; // scalar_map_container.h } @@ -724,6 +735,14 @@ class LIBPROTOBUF_EXPORT Reflection { const FieldDescriptor* field, MessageFactory* factory = NULL) const = 0; + // Appends an already-allocated object 'new_entry' to the repeated field + // specifyed by 'field' passing ownership to the message. + // TODO(tmarek): Make virtual after all subclasses have been + // updated. + virtual void AddAllocatedMessage(Message* message, + const FieldDescriptor* field, + Message* new_entry) const {} + // Get a RepeatedFieldRef object that can be used to read the underlying // repeated field. The type parameter T must be set according to the @@ -868,11 +887,20 @@ class LIBPROTOBUF_EXPORT Reflection { // on field->cpp_type(), // on field->field_option().ctype() (if ctype >= 0) // of field->message_type() (if message_type != NULL). - // We use 1 routine rather than 4 (const vs mutable) x (scalar vs pointer). + // We use 2 routine rather than 4 (const vs mutable) x (scalar vs pointer). virtual void* MutableRawRepeatedField( Message* message, const FieldDescriptor* field, FieldDescriptor::CppType, int ctype, const Descriptor* message_type) const = 0; + // TODO(jieluo) - make it pure virtual after updating all the subclasses. + virtual const void* GetRawRepeatedField( + const Message& message, const FieldDescriptor* field, + FieldDescriptor::CppType cpptype, int ctype, + const Descriptor* message_type) const { + return MutableRawRepeatedField( + const_cast(&message), field, cpptype, ctype, message_type); + } + // 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 @@ -887,6 +915,8 @@ class LIBPROTOBUF_EXPORT Reflection { // "message_type" should be set to its descriptor. Otherwise "message_type" // should be set to NULL. Implementations of this method should check whether // "cpp_type"/"message_type" is consistent with the actual type of the field. + // We use 1 routine rather than 2 (const vs mutable) because it is protected + // and it doesn't change the message. virtual void* RepeatedFieldData( Message* message, const FieldDescriptor* field, FieldDescriptor::CppType cpp_type, @@ -902,14 +932,73 @@ class LIBPROTOBUF_EXPORT Reflection { friend class RepeatedFieldRef; template friend class MutableRepeatedFieldRef; + friend class ::google::protobuf::python::MapReflectionFriend; // Special version for specialized implementations of string. We can't call // MutableRawRepeatedField directly here because we don't have access to // FieldOptions::* which are defined in descriptor.pb.h. Including that // file here is not possible because it would cause a circular include cycle. + // We use 1 routine rather than 2 (const vs mutable) because it is private + // and mutable a repeated string field doesn't change the message. void* MutableRawRepeatedString( Message* message, const FieldDescriptor* field, bool is_string) const; + friend class MapReflectionTester; + // TODO(jieluo) - make the map APIs pure virtual after updating + // all the subclasses. + // Returns true if key is in map. Returns false if key is not in map field. + virtual bool ContainsMapKey(const Message& message, + const FieldDescriptor* field, + const MapKey& key) const { + return false; + } + + // If key is in map field: Saves the value pointer to val and returns + // false. If key in not in map field: Insert the key into map, saves + // value pointer to val and retuns true. + virtual bool InsertOrLookupMapValue(Message* message, + const FieldDescriptor* field, + const MapKey& key, + MapValueRef* val) const { + return false; + } + + // Delete and returns true if key is in the map field. Returns false + // otherwise. + virtual bool DeleteMapValue(Message* message, + const FieldDescriptor* field, + const MapKey& key) const { + return false; + } + + // Returns a MaIterator referring to the first element in the map field. + // If the map field is empty, this function returns the same as + // reflection::MapEnd. Mutation to the field may invalidate the iterator. + virtual MapIterator MapBegin( + Message* message, + const FieldDescriptor* field) const; + + // Returns a MapIterator referring to the theoretical element that would + // follow the last element in the map field. It does not point to any + // real element. Mutation to the field may invalidate the iterator. + virtual MapIterator MapEnd( + Message* message, + const FieldDescriptor* field) const; + + // Get the number of pair of a map field. The result may be + // different from FieldSize which can have duplicate keys. + virtual int MapSize(const Message& message, + const FieldDescriptor* field) const { + return 0; + } + + // Help method for MapIterator. + friend class MapIterator; + virtual internal::MapFieldBase* MapData( + Message* message, const FieldDescriptor* field) const { + return NULL; + } + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reflection); }; @@ -1025,10 +1114,9 @@ inline RepeatedPtrField* Reflection::MutableRepeatedPtrField( template<> inline const RepeatedPtrField& Reflection::GetRepeatedPtrField( const Message& message, const FieldDescriptor* field) const { - return *static_cast* >( - MutableRawRepeatedField(const_cast(&message), field, - FieldDescriptor::CPPTYPE_MESSAGE, -1, - NULL)); + return *static_cast* >( + GetRawRepeatedField(message, field, FieldDescriptor::CPPTYPE_MESSAGE, + -1, NULL)); } template<> @@ -1043,10 +1131,9 @@ inline RepeatedPtrField* Reflection::MutableRepeatedPtrField( template inline const RepeatedPtrField& Reflection::GetRepeatedPtrField( const Message& message, const FieldDescriptor* field) const { - return *static_cast* >( - MutableRawRepeatedField(const_cast(&message), field, - FieldDescriptor::CPPTYPE_MESSAGE, -1, - PB::default_instance().GetDescriptor())); + return *static_cast* >( + GetRawRepeatedField(message, field, FieldDescriptor::CPPTYPE_MESSAGE, + -1, PB::default_instance().GetDescriptor())); } template diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index 4f63ad2b..5bd8bcfb 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc @@ -35,7 +35,9 @@ #include #include +#include #include +#include #include #include #include @@ -98,27 +100,19 @@ string InitializationErrorMessage(const char* action, // call MergePartialFromCodedStream(). However, when parsing very small // messages, every function call introduces significant overhead. To avoid // this without reproducing code, we use these forced-inline helpers. -// -// Note: GCC only allows GOOGLE_ATTRIBUTE_ALWAYS_INLINE on declarations, not -// definitions. +GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineMergeFromCodedStream( + io::CodedInputStream* input, MessageLite* message); +GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromCodedStream( + io::CodedInputStream* input, MessageLite* message); +GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromCodedStream( + io::CodedInputStream* input, MessageLite* message); +GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromArray( + const void* data, int size, MessageLite* message); +GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromArray( + const void* data, int size, MessageLite* message); + inline bool InlineMergeFromCodedStream(io::CodedInputStream* input, - MessageLite* message) - GOOGLE_ATTRIBUTE_ALWAYS_INLINE; -inline bool InlineParseFromCodedStream(io::CodedInputStream* input, - MessageLite* message) - GOOGLE_ATTRIBUTE_ALWAYS_INLINE; -inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input, - MessageLite* message) - GOOGLE_ATTRIBUTE_ALWAYS_INLINE; -inline bool InlineParseFromArray(const void* data, int size, - MessageLite* message) - GOOGLE_ATTRIBUTE_ALWAYS_INLINE; -inline bool InlineParsePartialFromArray(const void* data, int size, - MessageLite* message) - GOOGLE_ATTRIBUTE_ALWAYS_INLINE; - -bool InlineMergeFromCodedStream(io::CodedInputStream* input, - MessageLite* message) { + MessageLite* message) { if (!message->MergePartialFromCodedStream(input)) return false; if (!message->IsInitialized()) { GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *message); @@ -127,26 +121,27 @@ bool InlineMergeFromCodedStream(io::CodedInputStream* input, return true; } -bool InlineParseFromCodedStream(io::CodedInputStream* input, - MessageLite* message) { +inline bool InlineParseFromCodedStream(io::CodedInputStream* input, + MessageLite* message) { message->Clear(); return InlineMergeFromCodedStream(input, message); } -bool InlineParsePartialFromCodedStream(io::CodedInputStream* input, - MessageLite* message) { +inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input, + MessageLite* message) { message->Clear(); return message->MergePartialFromCodedStream(input); } -bool InlineParseFromArray(const void* data, int size, MessageLite* message) { +inline bool InlineParseFromArray( + const void* data, int size, MessageLite* message) { io::CodedInputStream input(reinterpret_cast(data), size); return InlineParseFromCodedStream(&input, message) && input.ConsumedEntireMessage(); } -bool InlineParsePartialFromArray(const void* data, int size, - MessageLite* message) { +inline bool InlineParsePartialFromArray( + const void* data, int size, MessageLite* message) { io::CodedInputStream input(reinterpret_cast(data), size); return InlineParsePartialFromCodedStream(&input, message) && input.ConsumedEntireMessage(); @@ -353,5 +348,18 @@ string MessageLite::SerializePartialAsString() const { return output; } +namespace internal { +template<> +MessageLite* GenericTypeHandler::NewFromPrototype( + const MessageLite* prototype, google::protobuf::Arena* arena) { + return prototype->New(arena); +} +template <> +void GenericTypeHandler::Merge(const MessageLite& from, + MessageLite* to) { + to->CheckTypeAndMergeFrom(from); +} +} // namespace internal + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc index 75d60b8b..2d4780fe 100644 --- a/src/google/protobuf/message_unittest.cc +++ b/src/google/protobuf/message_unittest.cc @@ -53,6 +53,7 @@ #include #include +#include #include #include #include diff --git a/src/google/protobuf/metadata.h b/src/google/protobuf/metadata.h index 30b2a6ee..fdee150b 100644 --- a/src/google/protobuf/metadata.h +++ b/src/google/protobuf/metadata.h @@ -69,8 +69,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena { ptr_ = NULL; } - inline const UnknownFieldSet& unknown_fields() const - GOOGLE_ATTRIBUTE_ALWAYS_INLINE { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE const UnknownFieldSet& unknown_fields() const { if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) { return PtrValue()->unknown_fields_; } else { @@ -78,7 +77,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena { } } - inline UnknownFieldSet* mutable_unknown_fields() GOOGLE_ATTRIBUTE_ALWAYS_INLINE { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE UnknownFieldSet* mutable_unknown_fields() { if (GOOGLE_PREDICT_TRUE(have_unknown_fields())) { return &PtrValue()->unknown_fields_; } else { @@ -86,7 +85,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena { } } - inline Arena* arena() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE Arena* arena() const { if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) { return PtrValue()->arena_; } else { @@ -94,11 +93,11 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena { } } - inline bool have_unknown_fields() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool have_unknown_fields() const { return PtrTag() == kTagContainer; } - inline void Swap(InternalMetadataWithArena* other) GOOGLE_ATTRIBUTE_ALWAYS_INLINE { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(InternalMetadataWithArena* other) { // Semantics here are that we swap only the unknown fields, not the arena // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in @@ -110,7 +109,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena { } } - inline void* raw_arena_ptr() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* raw_arena_ptr() const { return ptr_; } @@ -128,7 +127,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena { static const intptr_t kPtrValueMask = ~kPtrTagMask; // Accessors for pointer tag and pointer value. - inline int PtrTag() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE { + GOOGLE_ATTRIBUTE_ALWAYS_INLINE int PtrTag() const { return reinterpret_cast(ptr_) & kPtrTagMask; } @@ -143,7 +142,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena { Arena* arena_; }; - UnknownFieldSet* mutable_unknown_fields_slow() GOOGLE_ATTRIBUTE_NOINLINE { + GOOGLE_ATTRIBUTE_NOINLINE UnknownFieldSet* mutable_unknown_fields_slow() { Arena* my_arena = arena(); Container* container = Arena::Create(my_arena); ptr_ = reinterpret_cast( diff --git a/src/google/protobuf/no_field_presence_test.cc b/src/google/protobuf/no_field_presence_test.cc index 4b7b31d9..bc41beec 100644 --- a/src/google/protobuf/no_field_presence_test.cc +++ b/src/google/protobuf/no_field_presence_test.cc @@ -341,6 +341,46 @@ TEST(NoFieldPresenceTest, ReflectionHasFieldTest) { EXPECT_EQ(false, r->HasField(message, field_string)); } +TEST(NoFieldPresenceTest, ReflectionClearFieldTest) { + proto2_nofieldpresence_unittest::TestAllTypes message; + + const google::protobuf::Reflection* r = message.GetReflection(); + const google::protobuf::Descriptor* desc = message.GetDescriptor(); + + const google::protobuf::FieldDescriptor* field_int32 = desc->FindFieldByName( + "optional_int32"); + const google::protobuf::FieldDescriptor* field_double = desc->FindFieldByName( + "optional_double"); + const google::protobuf::FieldDescriptor* field_string = desc->FindFieldByName( + "optional_string"); + const google::protobuf::FieldDescriptor* field_message = desc->FindFieldByName( + "optional_nested_message"); + const google::protobuf::FieldDescriptor* field_lazy = desc->FindFieldByName( + "optional_lazy_message"); + + message.set_optional_int32(42); + r->ClearField(&message, field_int32); + EXPECT_EQ(0, message.optional_int32()); + + message.set_optional_double(42.0); + r->ClearField(&message, field_double); + EXPECT_EQ(0.0, message.optional_double()); + + message.set_optional_string("test"); + r->ClearField(&message, field_string); + EXPECT_EQ("", message.optional_string()); + + message.mutable_optional_nested_message()->set_bb(1234); + r->ClearField(&message, field_message); + EXPECT_FALSE(message.has_optional_nested_message()); + EXPECT_EQ(0, message.optional_nested_message().bb()); + + message.mutable_optional_lazy_message()->set_bb(42); + r->ClearField(&message, field_lazy); + EXPECT_FALSE(message.has_optional_lazy_message()); + EXPECT_EQ(0, message.optional_lazy_message().bb()); +} + TEST(NoFieldPresenceTest, HasFieldOneofsTest) { // check that HasField behaves properly for oneofs. proto2_nofieldpresence_unittest::TestAllTypes message; diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc index da4be673..2838e0fc 100644 --- a/src/google/protobuf/proto3_arena_unittest.cc +++ b/src/google/protobuf/proto3_arena_unittest.cc @@ -119,7 +119,7 @@ void ExpectAllFieldsSet(const TestAllTypes& m) { // proto3 and expect the arena support to be fully tested in proto2 unittests // because proto3 shares most code with proto2. -TEST(ArenaTest, Parsing) { +TEST(Proto3ArenaTest, Parsing) { TestAllTypes original; SetAllFields(&original); @@ -129,7 +129,7 @@ TEST(ArenaTest, Parsing) { ExpectAllFieldsSet(*arena_message); } -TEST(ArenaTest, UnknownFields) { +TEST(Proto3ArenaTest, UnknownFields) { TestAllTypes original; SetAllFields(&original); @@ -150,7 +150,7 @@ TEST(ArenaTest, UnknownFields) { arena_message->GetReflection()->GetUnknownFields(*arena_message).empty()); } -TEST(ArenaTest, Swap) { +TEST(Proto3ArenaTest, Swap) { Arena arena1; Arena arena2; @@ -162,7 +162,7 @@ TEST(ArenaTest, Swap) { EXPECT_EQ(&arena2, arena2_message->GetArena()); } -TEST(ArenaTest, SetAllocatedMessage) { +TEST(Proto3ArenaTest, SetAllocatedMessage) { Arena arena; TestAllTypes *arena_message = Arena::CreateMessage(&arena); TestAllTypes::NestedMessage* nested = new TestAllTypes::NestedMessage; @@ -171,7 +171,7 @@ TEST(ArenaTest, SetAllocatedMessage) { EXPECT_EQ(118, arena_message->optional_nested_message().bb()); } -TEST(ArenaTest, ReleaseMessage) { +TEST(Proto3ArenaTest, ReleaseMessage) { Arena arena; TestAllTypes* arena_message = Arena::CreateMessage(&arena); arena_message->mutable_optional_nested_message()->set_bb(118); @@ -180,7 +180,7 @@ TEST(ArenaTest, ReleaseMessage) { EXPECT_EQ(118, nested->bb()); } -TEST(ArenaTest, MessageFieldClear) { +TEST(Proto3ArenaTest, MessageFieldClear) { // GitHub issue #310: https://github.com/google/protobuf/issues/310 Arena arena; TestAllTypes* arena_message = Arena::CreateMessage(&arena); @@ -190,6 +190,20 @@ TEST(ArenaTest, MessageFieldClear) { arena_message->Clear(); } +TEST(Proto3ArenaTest, MessageFieldClearViaReflection) { + Arena arena; + TestAllTypes* message = Arena::CreateMessage(&arena); + const Reflection* r = message->GetReflection(); + const Descriptor* d = message->GetDescriptor(); + const FieldDescriptor* msg_field = d->FindFieldByName( + "optional_nested_message"); + + message->mutable_optional_nested_message()->set_bb(1); + r->ClearField(message, msg_field); + EXPECT_FALSE(message->has_optional_nested_message()); + EXPECT_EQ(0, message->optional_nested_message().bb()); +} + } // namespace } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/proto_cast.h b/src/google/protobuf/proto_cast.h index e25c219f..dc0e9aca 100644 --- a/src/google/protobuf/proto_cast.h +++ b/src/google/protobuf/proto_cast.h @@ -33,6 +33,7 @@ #include +#include #include // proto_cast<> is used to simulate over-the-wire conversion of one diff --git a/src/google/protobuf/proto_cast_test.cc b/src/google/protobuf/proto_cast_test.cc index eb101eb6..a8f43ae4 100644 --- a/src/google/protobuf/proto_cast_test.cc +++ b/src/google/protobuf/proto_cast_test.cc @@ -32,7 +32,7 @@ #include #include -#include +#include namespace google { using google::protobuf::util::UpRevision; diff --git a/src/google/protobuf/reflection.h b/src/google/protobuf/reflection.h index 4ff0f6b4..671aafdc 100755 --- a/src/google/protobuf/reflection.h +++ b/src/google/protobuf/reflection.h @@ -553,7 +553,7 @@ struct RefTypeTraits< template struct RefTypeTraits< - T, typename internal::enable_if::value>::type> { + T, typename internal::enable_if< ::google::protobuf::internal::is_same::value>::type> { typedef RepeatedFieldRefIterator iterator; typedef RepeatedFieldAccessor AccessorType; typedef string AccessorValueType; diff --git a/src/google/protobuf/reflection_ops_unittest.cc b/src/google/protobuf/reflection_ops_unittest.cc index 32740ea4..88d6bfb6 100644 --- a/src/google/protobuf/reflection_ops_unittest.cc +++ b/src/google/protobuf/reflection_ops_unittest.cc @@ -37,6 +37,7 @@ #include #include +#include #include #include #include diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc index e5aedadc..949e0a23 100644 --- a/src/google/protobuf/repeated_field.cc +++ b/src/google/protobuf/repeated_field.cc @@ -35,6 +35,7 @@ #include #include +#include #include namespace google { @@ -53,13 +54,17 @@ void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) { Arena* arena = GetArenaNoVirtual(); new_size = max(kMinRepeatedFieldAllocationSize, max(total_size_ * 2, new_size)); + GOOGLE_CHECK_LE(new_size, + (std::numeric_limits::max() - kRepHeaderSize) / + sizeof(old_rep->elements[0])) + << "Requested size is too large to fit into size_t."; if (arena == NULL) { rep_ = reinterpret_cast( - new char[kRepHeaderSize + sizeof(old_rep->elements[0])*new_size]); + new char[kRepHeaderSize + sizeof(old_rep->elements[0]) * new_size]); } else { rep_ = reinterpret_cast( ::google::protobuf::Arena::CreateArray(arena, - kRepHeaderSize + sizeof(old_rep->elements[0])*new_size)); + kRepHeaderSize + sizeof(old_rep->elements[0]) * new_size)); } total_size_ = new_size; if (old_rep && old_rep->allocated_size > 0) { diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index 14f46298..b42d4790 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -361,7 +362,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { // To parse directly into a proto2 generated class, the upb class GMR_Handlers // needs to be able to modify a RepeatedPtrFieldBase directly. - friend class LIBPROTOBUF_EXPORT upb::google_opensource::GMR_Handlers; + friend class upb::google_opensource::GMR_Handlers; RepeatedPtrFieldBase(); explicit RepeatedPtrFieldBase(::google::protobuf::Arena* arena); @@ -408,7 +409,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { const typename TypeHandler::Type* const* data() const; template - inline void Swap(RepeatedPtrFieldBase* other) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(RepeatedPtrFieldBase* other); void SwapElements(int index1, int index2); @@ -458,22 +459,20 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { void AddAllocatedInternal(typename TypeHandler::Type* value, google::protobuf::internal::false_type); - template + template GOOGLE_ATTRIBUTE_NOINLINE void AddAllocatedSlowWithCopy(typename TypeHandler::Type* value, Arena* value_arena, - Arena* my_arena) - GOOGLE_ATTRIBUTE_NOINLINE; - template - void AddAllocatedSlowWithoutCopy(typename TypeHandler::Type* value) - GOOGLE_ATTRIBUTE_NOINLINE; + Arena* my_arena); + template GOOGLE_ATTRIBUTE_NOINLINE + void AddAllocatedSlowWithoutCopy(typename TypeHandler::Type* value); template typename TypeHandler::Type* ReleaseLastInternal(google::protobuf::internal::true_type); template typename TypeHandler::Type* ReleaseLastInternal(google::protobuf::internal::false_type); - template - inline void SwapFallback(RepeatedPtrFieldBase* other) GOOGLE_ATTRIBUTE_NOINLINE; + template GOOGLE_ATTRIBUTE_NOINLINE + void SwapFallback(RepeatedPtrFieldBase* other); inline Arena* GetArenaNoVirtual() const { return arena_; @@ -542,20 +541,10 @@ class GenericTypeHandler { } // We force NewFromPrototype() and Delete() to be non-inline to reduce code // size: else, several other methods get inlined copies of message types' - // constructors and destructors. Note that the GOOGLE_ATTRIBUTE_NOINLINE macro - // requires the 'inline' storage class here, which is somewhat confusing, but - // the compiler does the right thing. - static inline GenericType* NewFromPrototype(const GenericType* prototype, - ::google::protobuf::Arena* arena = NULL) - GOOGLE_ATTRIBUTE_NOINLINE { - return New(arena); - } - static inline void Delete(GenericType* value, Arena* arena) - GOOGLE_ATTRIBUTE_NOINLINE { - if (arena == NULL) { - delete value; - } - } + // constructors and destructors. + GOOGLE_ATTRIBUTE_NOINLINE static GenericType* NewFromPrototype( + const GenericType* prototype, ::google::protobuf::Arena* arena = NULL); + GOOGLE_ATTRIBUTE_NOINLINE static void Delete(GenericType* value, Arena* arena); static inline ::google::protobuf::Arena* GetArena(GenericType* value) { return ::google::protobuf::Arena::GetArena(value); } @@ -564,10 +553,8 @@ class GenericTypeHandler { } static inline void Clear(GenericType* value) { value->Clear(); } - static inline void Merge(const GenericType& from, GenericType* to) - GOOGLE_ATTRIBUTE_NOINLINE { - to->MergeFrom(from); - } + GOOGLE_ATTRIBUTE_NOINLINE static void Merge(const GenericType& from, + GenericType* to); static inline int SpaceUsed(const GenericType& value) { return value.SpaceUsed(); } @@ -576,11 +563,31 @@ class GenericTypeHandler { } }; -template<> -inline MessageLite* GenericTypeHandler::NewFromPrototype( - const MessageLite* prototype, google::protobuf::Arena* arena) { - return prototype->New(arena); +template +GenericType* GenericTypeHandler::NewFromPrototype( + const GenericType* prototype, ::google::protobuf::Arena* arena) { + return New(arena); +} +template +void GenericTypeHandler::Delete(GenericType* value, Arena* arena) { + if (arena == NULL) { + delete value; + } } +template +void GenericTypeHandler::Merge(const GenericType& from, + GenericType* to) { + to->MergeFrom(from); +} + +// NewFromPrototype() and Merge() cannot be defined here; if they're declared +// inline the compiler will complain about not matching GOOGLE_ATTRIBUTE_NOINLINE +// above, and if not, compilation will result in multiple definitions. These +// are therefore declared as specializations here and defined in +// message_lite.cc. +template<> +MessageLite* GenericTypeHandler::NewFromPrototype( + const MessageLite* prototype, google::protobuf::Arena* arena); template<> inline google::protobuf::Arena* GenericTypeHandler::GetArena( MessageLite* value) { @@ -591,14 +598,9 @@ inline void* GenericTypeHandler::GetMaybeArenaPointer( MessageLite* value) { return value->GetMaybeArenaPointer(); } - -// Implements GenericTypeHandler specialization required by RepeatedPtrFields -// to work with MessageLite type. template <> -inline void GenericTypeHandler::Merge( - const MessageLite& from, MessageLite* to) { - to->CheckTypeAndMergeFrom(from); -} +void GenericTypeHandler::Merge(const MessageLite& from, + MessageLite* to); // Declarations of the specialization as we cannot define them here, as the // header that defines ProtocolMessage depends on types defined in this header. @@ -1221,13 +1223,17 @@ void RepeatedField::Reserve(int new_size) { Arena* arena = GetArenaNoVirtual(); new_size = max(google::protobuf::internal::kMinRepeatedFieldAllocationSize, max(total_size_ * 2, new_size)); + GOOGLE_CHECK_LE(new_size, + (std::numeric_limits::max() - kRepHeaderSize) / + sizeof(Element)) + << "Requested size is too large to fit into size_t."; if (arena == NULL) { rep_ = reinterpret_cast( - new char[kRepHeaderSize + sizeof(Element)*new_size]); + new char[kRepHeaderSize + sizeof(Element) * new_size]); } else { rep_ = reinterpret_cast( ::google::protobuf::Arena::CreateArray(arena, - kRepHeaderSize + sizeof(Element)*new_size)); + kRepHeaderSize + sizeof(Element) * new_size)); } rep_->arena = arena; int old_total_size = total_size_; @@ -1342,7 +1348,7 @@ inline void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) { } template -inline void RepeatedPtrFieldBase::SwapFallback(RepeatedPtrFieldBase* other) { +void RepeatedPtrFieldBase::SwapFallback(RepeatedPtrFieldBase* other) { GOOGLE_DCHECK(other->GetArenaNoVirtual() != GetArenaNoVirtual()); // Copy semantics in this case. We try to improve efficiency by placing the diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc index af397932..b45664b0 100644 --- a/src/google/protobuf/repeated_field_unittest.cc +++ b/src/google/protobuf/repeated_field_unittest.cc @@ -42,6 +42,7 @@ #include +#include #include #include #include @@ -1429,7 +1430,6 @@ class RepeatedFieldInsertionIteratorsTest : public testing::Test { std::copy(nested_ptrs.begin(), nested_ptrs.end(), RepeatedFieldBackInserter( protobuffer.mutable_repeated_nested_message())); - } virtual void TearDown() { diff --git a/src/google/protobuf/service.h b/src/google/protobuf/service.h index cc0b45d4..ad6f9685 100644 --- a/src/google/protobuf/service.h +++ b/src/google/protobuf/service.h @@ -74,12 +74,12 @@ // // To call a remote MyServiceImpl, first you need an RpcChannel connected to it. // How to construct a channel depends, again, on your RPC implementation. -// Here we use a hypothentical "MyRpcChannel" as an example: +// Here we use a hypothetical "MyRpcChannel" as an example: // MyRpcChannel channel("rpc:hostname:1234/myservice"); // MyRpcController controller; // MyServiceImpl::Stub stub(&channel); // FooRequest request; -// FooRespnose response; +// FooResponse response; // // // ... fill in request ... // @@ -102,6 +102,7 @@ #include #include +#include namespace google { namespace protobuf { diff --git a/src/google/protobuf/test_util.cc b/src/google/protobuf/test_util.cc index be1c90e0..07aa1d77 100644 --- a/src/google/protobuf/test_util.cc +++ b/src/google/protobuf/test_util.cc @@ -42,6 +42,7 @@ #include #include +#include #include #include #include diff --git a/src/google/protobuf/test_util_lite.cc b/src/google/protobuf/test_util_lite.cc index 88eca0ad..388c0cbd 100644 --- a/src/google/protobuf/test_util_lite.cc +++ b/src/google/protobuf/test_util_lite.cc @@ -33,6 +33,7 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include +#include #include diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc index 76ce9875..1aafd8e6 100644 --- a/src/google/protobuf/text_format_unittest.cc +++ b/src/google/protobuf/text_format_unittest.cc @@ -38,11 +38,13 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include diff --git a/src/google/protobuf/unittest_mset.proto b/src/google/protobuf/unittest_mset.proto index 3aa31fa9..49d9adad 100644 --- a/src/google/protobuf/unittest_mset.proto +++ b/src/google/protobuf/unittest_mset.proto @@ -32,33 +32,31 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. // -// This file contains messages for testing message_set_wire_format. +// This file is similar to unittest_mset_wire_format.proto, but does not +// have a TestMessageSet, so it can be downgraded to proto1. syntax = "proto2"; + +import "google/protobuf/unittest_mset_wire_format.proto"; + package protobuf_unittest; option cc_enable_arenas = true; option optimize_for = SPEED; -// A message with message_set_wire_format. -message TestMessageSet { - option message_set_wire_format = true; - extensions 4 to max; -} - message TestMessageSetContainer { - optional TestMessageSet message_set = 1; + optional proto2_wireformat_unittest.TestMessageSet message_set = 1; } message TestMessageSetExtension1 { - extend TestMessageSet { + extend proto2_wireformat_unittest.TestMessageSet { optional TestMessageSetExtension1 message_set_extension = 1545008; } optional int32 i = 15; } message TestMessageSetExtension2 { - extend TestMessageSet { + extend proto2_wireformat_unittest.TestMessageSet { optional TestMessageSetExtension2 message_set_extension = 1547769; } optional string str = 25; @@ -82,4 +80,3 @@ message RawMessageSet { required bytes message = 3; } } - diff --git a/src/google/protobuf/unknown_enum_impl.h b/src/google/protobuf/unknown_enum_impl.h index 39c10cbc..7c68ad6c 100644 --- a/src/google/protobuf/unknown_enum_impl.h +++ b/src/google/protobuf/unknown_enum_impl.h @@ -34,7 +34,6 @@ #include #include -#include "net/proto/tagmapper.h" #include namespace google { @@ -59,10 +58,10 @@ namespace util { // In proto2, invalid enum values will be treated as unknown fields. This // function checks that case. bool HasUnknownEnum(const Message& message, int32 field_number, - int32* unknown_value = nullptr); + int32* unknown_value = NULL); // Same as above, but returns all unknown enums. bool GetRepeatedEnumUnknowns(const Message& message, int32 field_number, - vector* unknown_values = nullptr); + vector* unknown_values = NULL); // In proto1, invalue enum values are stored in the same way as valid enum // values. // TODO(karner): Delete this once the migration to proto2 is complete. @@ -75,7 +74,7 @@ bool GetRepeatedEnumUnknownsProto1(const Message& message, int32 field_number, // or proto2. template bool HasUnknownEnum_Template(const T& message, int32 field_number, - int32* unknown_value = nullptr) { + int32* unknown_value = NULL) { if (internal::is_base_of::value || !internal::is_base_of::value) { return HasUnknownEnum(message, field_number, unknown_value); @@ -88,7 +87,7 @@ bool HasUnknownEnum_Template(const T& message, int32 field_number, template bool GetRepeatedEnumUnknowns_Template( const T& message, int32 field_number, - vector* unknown_values = nullptr) { + vector* unknown_values = NULL) { if (internal::is_base_of::value || !internal::is_base_of::value) { return GetRepeatedEnumUnknowns(message, field_number, unknown_values); diff --git a/src/google/protobuf/unknown_enum_test.proto b/src/google/protobuf/unknown_enum_test.proto index 0ea1ede3..3c549cc7 100644 --- a/src/google/protobuf/unknown_enum_test.proto +++ b/src/google/protobuf/unknown_enum_test.proto @@ -36,6 +36,8 @@ syntax = "proto2"; package google.protobuf.util; +option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; + 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 93f0f206..d4e383da 100644 --- a/src/google/protobuf/unknown_field_set.cc +++ b/src/google/protobuf/unknown_field_set.cc @@ -34,6 +34,7 @@ #include +#include #include #include #include diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h index 6781cd0f..612a942a 100644 --- a/src/google/protobuf/unknown_field_set.h +++ b/src/google/protobuf/unknown_field_set.h @@ -42,6 +42,7 @@ #include #include #include +#include namespace google { namespace protobuf { diff --git a/src/google/protobuf/unknown_field_set_unittest.cc b/src/google/protobuf/unknown_field_set_unittest.cc index 9b02f0b0..5de72630 100644 --- a/src/google/protobuf/unknown_field_set_unittest.cc +++ b/src/google/protobuf/unknown_field_set_unittest.cc @@ -43,7 +43,10 @@ #include #include +#include #include +#include +#include #include #include #include diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc index 944fb2e3..ea360798 100644 --- a/src/google/protobuf/util/internal/datapiece.cc +++ b/src/google/protobuf/util/internal/datapiece.cc @@ -79,7 +79,9 @@ StatusOr NumberConvertAndCheck(From before) { // For conversion between double and float only. template StatusOr FloatingPointConvertAndCheck(From before) { - if (MathLimits::IsNaN(before)) return std::numeric_limits::quiet_NaN(); + if (MathLimits::IsNaN(before)) { + return std::numeric_limits::quiet_NaN(); + } To after = static_cast(before); if (MathUtil::AlmostEquals(after, before)) { @@ -167,7 +169,7 @@ StatusOr DataPiece::ToString() const { return str_.ToString(); case TYPE_BYTES: { string base64; - WebSafeBase64Escape(str_, &base64); + Base64Escape(str_, &base64); return base64; } default: diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc index 267e2cd3..97b248ff 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter.cc +++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc @@ -46,6 +46,7 @@ DefaultValueObjectWriter::DefaultValueObjectWriter( TypeResolver* type_resolver, const google::protobuf::Type& type, ObjectWriter* ow) : typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), + own_typeinfo_(true), type_(type), disable_normalize_(false), current_(NULL), @@ -56,6 +57,9 @@ DefaultValueObjectWriter::~DefaultValueObjectWriter() { for (int i = 0; i < string_values_.size(); ++i) { delete string_values_[i]; } + if (own_typeinfo_) { + delete typeinfo_; + } } DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBool(StringPiece name, @@ -197,33 +201,47 @@ 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. + + // Render maps. Empty maps are rendered as "{}". + if (kind_ == MAP) { + ow->StartObject(name_); + WriteChildren(ow); + ow->EndObject(); return; } + + // Write out lists. If we didn't have any list in response, write out empty + // list. if (kind_ == LIST) { ow->StartList(name_); - } else { - ow->StartObject(name_); + WriteChildren(ow); + ow->EndList(); + return; } + + // If is_placeholder_ = true, we didn't see this node in the response, so + // skip output. + if (is_placeholder_) return; + + ow->StartObject(name_); + WriteChildren(ow); + ow->EndObject(); +} + +void DefaultValueObjectWriter::Node::WriteChildren(ObjectWriter* ow) { 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) { + const google::protobuf::Type& found_type, const 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) { @@ -248,7 +266,8 @@ const google::protobuf::Type* DefaultValueObjectWriter::Node::GetMapValueType( return NULL; } -void DefaultValueObjectWriter::Node::PopulateChildren(TypeInfo* typeinfo) { +void DefaultValueObjectWriter::Node::PopulateChildren( + const 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. @@ -310,15 +329,17 @@ void DefaultValueObjectWriter::Node::PopulateChildren(TypeInfo* typeinfo) { 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. + if (field.oneof_index() != 0) continue; + + // If the child field is of primitive type, sets its data to the default + // value of its type. google::protobuf::scoped_ptr child( - new Node(field.name(), field_type, kind, - ((kind == PRIMITIVE && field.oneof_index() == 0) - ? CreateDefaultDataPieceForField(field) - : DataPiece::NullData()), + new Node(field.json_name(), field_type, kind, + kind == PRIMITIVE ? CreateDefaultDataPieceForField(field) + : DataPiece::NullData(), true)); new_children.push_back(child.release()); } @@ -338,7 +359,7 @@ void DefaultValueObjectWriter::MaybePopulateChildrenOfAny(Node* node) { // 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()); + node->PopulateChildren(typeinfo_); } } @@ -388,7 +409,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject( root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(), false)); root_->set_disable_normalize(GetAndResetDisableNormalize()); - root_->PopulateChildren(typeinfo_.get()); + root_->PopulateChildren(typeinfo_); current_ = root_.get(); return this; } @@ -409,7 +430,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject( child->set_is_placeholder(false); child->set_disable_normalize(GetAndResetDisableNormalize()); if (child->kind() == OBJECT && child->number_of_children() == 0) { - child->PopulateChildren(typeinfo_.get()); + child->PopulateChildren(typeinfo_); } stack_.push(current_); @@ -492,12 +513,11 @@ void DefaultValueObjectWriter::RenderDataPiece(StringPiece name, // 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()); + current_->PopulateChildren(typeinfo_); } } 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( new Node(name.ToString(), NULL, PRIMITIVE, data, false)); diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h index 759ba91b..2468c8d9 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter.h +++ b/src/google/protobuf/util/internal/default_value_objectwriter.h @@ -57,7 +57,7 @@ namespace converter { // 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 { +class DefaultValueObjectWriter : public ObjectWriter { public: DefaultValueObjectWriter(TypeResolver* type_resolver, const google::protobuf::Type& type, @@ -129,7 +129,7 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { // 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); + void PopulateChildren(const 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 @@ -165,7 +165,10 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { // 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); + const google::protobuf::Type& entry_type, const TypeInfo* typeinfo); + + // Calls WriteTo() on every child in children_. + void WriteChildren(ObjectWriter* ow); // The name of this node. string name_; @@ -210,7 +213,9 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { // 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_; + const TypeInfo* typeinfo_; + // Whether the TypeInfo object is owned by this class. + bool own_typeinfo_; // google::protobuf::Type of the root message type. const google::protobuf::Type& type_; // Holds copies of strings passed to RenderString. diff --git a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc index 593c7105..237d0722 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc +++ b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc @@ -73,15 +73,15 @@ INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, 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", "") + ->RenderDouble("doubleValue", 0.0) + ->RenderFloat("floatValue", 0.0) + ->RenderInt64("int64Value", 0) + ->RenderUint64("uint64Value", 0) + ->RenderInt32("int32Value", 0) + ->RenderUint32("uint32Value", 0) + ->RenderBool("boolValue", false) + ->RenderString("stringValue", "") + ->RenderBytes("bytesValue", "") ->EndObject(); // Actual testing @@ -91,42 +91,42 @@ TEST_P(DefaultValueObjectWriterTest, Empty) { 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", "") + ->RenderDouble("doubleValue", 1.0) + ->RenderFloat("floatValue", 0.0) + ->RenderInt64("int64Value", 0) + ->RenderUint64("uint64Value", 0) + ->RenderInt32("int32Value", 0) + ->RenderUint32("uint32Value", 0) + ->RenderBool("boolValue", false) + ->RenderString("stringValue", "") ->EndObject(); // Actual testing - testing_->StartObject("")->RenderDouble("double_value", 1.0)->EndObject(); + testing_->StartObject("")->RenderDouble("doubleValue", 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", "") + ->RenderDouble("doubleValue", 1.0) + ->RenderFloat("floatValue", 0.0) + ->RenderInt64("int64Value", 0) + ->RenderUint64("uint64Value", 0) + ->RenderInt32("int32Value", 0) + ->RenderUint32("uint32Value", 0) + ->RenderBool("boolValue", false) + ->RenderString("stringValue", "") ->RenderString("unknown", "abc") - ->StartObject("unknown_object") + ->StartObject("unknownObject") ->RenderString("unknown", "def") ->EndObject() ->EndObject(); // Actual testing testing_->StartObject("") - ->RenderDouble("double_value", 1.0) + ->RenderDouble("doubleValue", 1.0) ->RenderString("unknown", "abc") - ->StartObject("unknown_object") + ->StartObject("unknownObject") ->RenderString("unknown", "def") ->EndObject() ->EndObject(); diff --git a/src/google/protobuf/util/internal/error_listener.h b/src/google/protobuf/util/internal/error_listener.h index 9b907df5..2699684d 100644 --- a/src/google/protobuf/util/internal/error_listener.h +++ b/src/google/protobuf/util/internal/error_listener.h @@ -37,7 +37,9 @@ #endif #include +#include #include +#include #include #include diff --git a/src/google/protobuf/util/internal/field_mask_utility.cc b/src/google/protobuf/util/internal/field_mask_utility.cc index 92468959..f0e8fc88 100644 --- a/src/google/protobuf/util/internal/field_mask_utility.cc +++ b/src/google/protobuf/util/internal/field_mask_utility.cc @@ -34,7 +34,6 @@ #include namespace google { - namespace protobuf { namespace util { namespace converter { @@ -138,7 +137,7 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths, } // Un-escaped '"' must be followed with a ']'. if (i >= length - 1 || paths[i + 1] != ']') { - return CreatePublicError( + return util::Status( util::error::INVALID_ARGUMENT, StrCat("Invalid FieldMask '", paths, "'. Map keys should be represented as [\"some_key\"].")); @@ -150,7 +149,7 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths, // 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( + return util::Status( util::error::INVALID_ARGUMENT, StrCat("Invalid FieldMask '", paths, "'. Map keys should be at the end of a path segment.")); @@ -162,7 +161,7 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths, // 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( + return util::Status( util::error::INVALID_ARGUMENT, StrCat("Invalid FieldMask '", paths, "'. Map keys should be represented as [\"some_key\"].")); @@ -198,7 +197,7 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths, // Removes the last prefix after seeing a ')'. if (i < length && paths[i] == ')') { if (prefix.empty()) { - return CreatePublicError( + return util::Status( util::error::INVALID_ARGUMENT, StrCat("Invalid FieldMask '", paths, "'. Cannot find matching '(' for all ')'.")); @@ -208,16 +207,14 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths, previous_position = i + 1; } if (in_map_key) { - return CreatePublicError( - util::error::INVALID_ARGUMENT, - StrCat("Invalid FieldMask '", paths, - "'. Cannot find matching ']' for all '['.")); + return util::Status(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(util::error::INVALID_ARGUMENT, + StrCat("Invalid FieldMask '", paths, + "'. Cannot find matching ')' for all '('.")); } return util::Status::OK; } diff --git a/src/google/protobuf/util/internal/json_escaping.cc b/src/google/protobuf/util/internal/json_escaping.cc index 5ac23421..36dc8ef9 100644 --- a/src/google/protobuf/util/internal/json_escaping.cc +++ b/src/google/protobuf/util/internal/json_escaping.cc @@ -30,6 +30,7 @@ #include +#include #include namespace google { diff --git a/src/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc index 0c41515f..d88a81f9 100644 --- a/src/google/protobuf/util/internal/json_objectwriter.cc +++ b/src/google/protobuf/util/internal/json_objectwriter.cc @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -142,7 +143,7 @@ JsonObjectWriter* JsonObjectWriter::RenderBytes(StringPiece name, StringPiece value) { WritePrefix(name); string base64; - WebSafeBase64EscapeWithPadding(value, &base64); + Base64Escape(value, &base64); WriteChar('"'); // TODO(wpoon): Consider a ByteSink solution that writes the base64 bytes // directly to the stream, rather than first putting them diff --git a/src/google/protobuf/util/internal/json_objectwriter_test.cc b/src/google/protobuf/util/internal/json_objectwriter_test.cc index df9a133e..dcd60601 100644 --- a/src/google/protobuf/util/internal/json_objectwriter_test.cc +++ b/src/google/protobuf/util/internal/json_objectwriter_test.cc @@ -47,7 +47,8 @@ class JsonObjectWriterTest : public ::testing::Test { JsonObjectWriterTest() : str_stream_(new StringOutputStream(&output_)), out_stream_(new CodedOutputStream(str_stream_)), - ow_(NULL) {} + ow_(NULL) { + } virtual ~JsonObjectWriterTest() { delete ow_; @@ -63,34 +64,36 @@ class JsonObjectWriterTest : public ::testing::Test { TEST_F(JsonObjectWriterTest, EmptyRootObject) { ow_ = new JsonObjectWriter("", out_stream_); - ow_->StartObject("")->EndObject(); + 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(); + ->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(); + 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(); + ->RenderString("test", "value") + ->StartList("empty") + ->EndList() + ->EndObject(); EXPECT_EQ("{\"test\":\"value\",\"empty\":[]}", output_.substr(0, out_stream_->ByteCount())); } @@ -98,10 +101,10 @@ TEST_F(JsonObjectWriterTest, EmptyList) { TEST_F(JsonObjectWriterTest, ObjectInObject) { ow_ = new JsonObjectWriter("", out_stream_); ow_->StartObject("") - ->StartObject("nested") - ->RenderString("field", "value") - ->EndObject() - ->EndObject(); + ->StartObject("nested") + ->RenderString("field", "value") + ->EndObject() + ->EndObject(); EXPECT_EQ("{\"nested\":{\"field\":\"value\"}}", output_.substr(0, out_stream_->ByteCount())); } @@ -109,10 +112,10 @@ TEST_F(JsonObjectWriterTest, ObjectInObject) { TEST_F(JsonObjectWriterTest, ListInObject) { ow_ = new JsonObjectWriter("", out_stream_); ow_->StartObject("") - ->StartList("nested") - ->RenderString("", "value") - ->EndList() - ->EndObject(); + ->StartList("nested") + ->RenderString("", "value") + ->EndList() + ->EndObject(); EXPECT_EQ("{\"nested\":[\"value\"]}", output_.substr(0, out_stream_->ByteCount())); } @@ -120,10 +123,10 @@ TEST_F(JsonObjectWriterTest, ListInObject) { TEST_F(JsonObjectWriterTest, ObjectInList) { ow_ = new JsonObjectWriter("", out_stream_); ow_->StartList("") - ->StartObject("") - ->RenderString("field", "value") - ->EndObject() - ->EndList(); + ->StartObject("") + ->RenderString("field", "value") + ->EndObject() + ->EndList(); EXPECT_EQ("[{\"field\":\"value\"}]", output_.substr(0, out_stream_->ByteCount())); } @@ -131,10 +134,10 @@ TEST_F(JsonObjectWriterTest, ObjectInList) { TEST_F(JsonObjectWriterTest, ListInList) { ow_ = new JsonObjectWriter("", out_stream_); ow_->StartList("") - ->StartList("") - ->RenderString("", "value") - ->EndList() - ->EndList(); + ->StartList("") + ->RenderString("", "value") + ->EndList() + ->EndList(); EXPECT_EQ("[[\"value\"]]", output_.substr(0, out_stream_->ByteCount())); } @@ -164,97 +167,95 @@ TEST_F(JsonObjectWriterTest, RenderPrimitives) { output_.substr(0, out_stream_->ByteCount())); } -TEST_F(JsonObjectWriterTest, BytesEncodesAsWebSafeBase64) { +TEST_F(JsonObjectWriterTest, BytesEncodesAsNonWebSafeBase64) { 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=\"}", + 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())); + ->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())); + ->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())); + ->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())); + ->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", "'<>&\\\"\r\n")->EndObject(); + ow_->StartObject("") + ->RenderString("string", "'<>&\\\"\r\n") + ->EndObject(); EXPECT_EQ("{\"string\":\"'\\u003c\\u003e&\\\\\\\"\\r\\n\"}", output_.substr(0, out_stream_->ByteCount())); } @@ -262,13 +263,13 @@ TEST_F(JsonObjectWriterTest, StringsEscapedAndEnclosedInDoubleQuotes) { TEST_F(JsonObjectWriterTest, Stringification) { ow_ = new JsonObjectWriter("", out_stream_); ow_->StartObject("") - ->RenderDouble("double_nan", std::numeric_limits::quiet_NaN()) - ->RenderFloat("float_nan", std::numeric_limits::quiet_NaN()) - ->RenderDouble("double_pos", std::numeric_limits::infinity()) - ->RenderFloat("float_pos", std::numeric_limits::infinity()) - ->RenderDouble("double_neg", -std::numeric_limits::infinity()) - ->RenderFloat("float_neg", -std::numeric_limits::infinity()) - ->EndObject(); + ->RenderDouble("double_nan", std::numeric_limits::quiet_NaN()) + ->RenderFloat("float_nan", std::numeric_limits::quiet_NaN()) + ->RenderDouble("double_pos", std::numeric_limits::infinity()) + ->RenderFloat("float_pos", std::numeric_limits::infinity()) + ->RenderDouble("double_neg", -std::numeric_limits::infinity()) + ->RenderFloat("float_neg", -std::numeric_limits::infinity()) + ->EndObject(); EXPECT_EQ( "{\"double_nan\":\"NaN\"," "\"float_nan\":\"NaN\"," diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc index d439a221..a7ef7fe2 100644 --- a/src/google/protobuf/util/internal/json_stream_parser.cc +++ b/src/google/protobuf/util/internal/json_stream_parser.cc @@ -40,6 +40,7 @@ #include #endif +#include #include #include #include @@ -104,16 +105,42 @@ JsonStreamParser::JsonStreamParser(ObjectWriter* ow) parsed_(), parsed_storage_(), string_open_(0), - utf8_storage_(), - utf8_length_(0) { + chunk_storage_(), + coerce_to_utf8_(false) { // Initialize the stack with a single value to be parsed. stack_.push(VALUE); } JsonStreamParser::~JsonStreamParser() {} + util::Status JsonStreamParser::Parse(StringPiece json) { - return ParseChunk(json); + StringPiece chunk = json; + // 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()) { + // Don't point chunk to leftover_ because leftover_ will be updated in + // ParseChunk(chunk). + chunk_storage_.swap(leftover_); + json.AppendToString(&chunk_storage_); + chunk = StringPiece(chunk_storage_); + } + + // Find the structurally valid UTF8 prefix and parse only that. + int n = internal::UTF8SpnStructurallyValid(chunk); + if (n > 0) { + util::Status status = ParseChunk(chunk.substr(0, n)); + + // Any leftover characters are stashed in leftover_ for later parsing when + // there is more data available. + chunk.substr(n).AppendToString(&leftover_); + return status; + } else { + chunk.CopyToString(&leftover_); + return util::Status::OK; + } } util::Status JsonStreamParser::FinishParse() { @@ -122,9 +149,22 @@ util::Status JsonStreamParser::FinishParse() { if (stack_.empty() && leftover_.empty()) { return util::Status::OK; } + + // Storage for UTF8-coerced string. + google::protobuf::scoped_array utf8; + if (coerce_to_utf8_) { + utf8.reset(new char[leftover_.size()]); + char* coerced = internal::UTF8CoerceToStructurallyValid(leftover_, utf8.get(), ' '); + p_ = json_ = StringPiece(coerced, leftover_.size()); + } else { + if (!internal::IsStructurallyValidUTF8(leftover_)) { + return ReportFailure("Encountered non UTF-8 code points."); + } + p_ = json_ = leftover_; + } + // 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()) { @@ -137,16 +177,10 @@ util::Status JsonStreamParser::FinishParse() { } 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; - } + // Do not do any work if the chunk is empty. + if (chunk.empty()) return util::Status::OK; + + p_ = json_ = chunk; finishing_ = false; util::Status result = RunParser(); diff --git a/src/google/protobuf/util/internal/json_stream_parser.h b/src/google/protobuf/util/internal/json_stream_parser.h index 17b094ae..0278c28f 100644 --- a/src/google/protobuf/util/internal/json_stream_parser.h +++ b/src/google/protobuf/util/internal/json_stream_parser.h @@ -75,12 +75,14 @@ class LIBPROTOBUF_EXPORT JsonStreamParser { explicit JsonStreamParser(ObjectWriter* ow); virtual ~JsonStreamParser(); - // Parse a JSON string (UTF-8 encoded). + // Parses a UTF-8 encoded JSON string from a StringPiece. util::Status Parse(StringPiece json); + // Finish parsing the JSON string. util::Status FinishParse(); + private: enum TokenType { BEGIN_STRING, // " or ' @@ -239,11 +241,11 @@ class LIBPROTOBUF_EXPORT JsonStreamParser { // A value of 0 indicates that string parsing is not in process. char string_open_; - // Storage for utf8-coerced bytes. - google::protobuf::scoped_array utf8_storage_; + // Storage for the chunk that are being parsed in ParseChunk(). + string chunk_storage_; - // Length of the storage for utf8-coerced bytes. - int utf8_length_; + // Whether to allow non UTF-8 encoded input and replace invalid code points. + bool coerce_to_utf8_; GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonStreamParser); }; diff --git a/src/google/protobuf/util/internal/json_stream_parser_test.cc b/src/google/protobuf/util/internal/json_stream_parser_test.cc index b0775a2f..c833ed1f 100644 --- a/src/google/protobuf/util/internal/json_stream_parser_test.cc +++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc @@ -30,6 +30,7 @@ #include +#include #include #include #include @@ -85,7 +86,7 @@ class JsonStreamParserTest : public ::testing::Test { JsonStreamParserTest() : mock_(), ow_(&mock_) {} virtual ~JsonStreamParserTest() {} - util::Status RunTest(StringPiece json, int split) { + util::Status RunTest(StringPiece json, int split, bool coerce_utf8 = false) { JsonStreamParser parser(&mock_); // Special case for split == length, test parsing one character at a time. @@ -115,8 +116,8 @@ class JsonStreamParserTest : public ::testing::Test { return result; } - void DoTest(StringPiece json, int split) { - util::Status result = RunTest(json, split); + void DoTest(StringPiece json, int split, bool coerce_utf8 = false) { + util::Status result = RunTest(json, split, coerce_utf8); if (!result.ok()) { GOOGLE_LOG(WARNING) << result; } @@ -337,14 +338,26 @@ TEST_F(JsonStreamParserTest, ObjectValues) { } } + +TEST_F(JsonStreamParserTest, RejectNonUtf8WhenNotCoerced) { + StringPiece json = "{\"address\":\xFF\"חרושת 23, רעננה, ישראל\"}"; + for (int i = 0; i <= json.length(); ++i) { + DoErrorTest(json, i, "Encountered non UTF-8 code points."); + } + json = "{\"address\": \"חרושת 23,\xFFרעננה, ישראל\"}"; + for (int i = 0; i <= json.length(); ++i) { + DoErrorTest(json, i, "Encountered non UTF-8 code points."); + } +} + #ifndef _MSC_VER // - unicode handling in strings TEST_F(JsonStreamParserTest, UnicodeEscaping) { StringPiece str = "[\"\\u0639\\u0631\\u0628\\u0649\"]"; for (int i = 0; i <= str.length(); ++i) { // TODO(xiaofeng): Figure out what default encoding to use for JSON strings. - // In protobuf we use UTF-8 for strings, but for JSON we probably should allow - // different encodings? + // 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); } diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc index 53a0e47a..18bb2772 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource.cc @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -96,7 +97,7 @@ ProtoStreamObjectSource::ProtoStreamObjectSource( } ProtoStreamObjectSource::ProtoStreamObjectSource( - google::protobuf::io::CodedInputStream* stream, TypeInfo* typeinfo, + google::protobuf::io::CodedInputStream* stream, const 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."; @@ -156,7 +157,7 @@ Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type, last_tag = tag; field = FindAndVerifyField(type, tag); if (field != NULL) { - field_name = field->name(); + field_name = field->json_name(); } } if (field == NULL) { @@ -214,7 +215,7 @@ StatusOr 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()); + typeinfo_->GetTypeByTypeUrl(field->type_url()); uint32 tag_to_return = 0; if (IsPackable(*field) && list_tag == @@ -784,7 +785,8 @@ Status ProtoStreamObjectSource::RenderField( // 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()); + const google::protobuf::Enum* en = + typeinfo_->GetEnumByTypeUrl(field->type_url()); // Lookup the name of the enum, and render that. Skips unknown enums. if (en != NULL) { const google::protobuf::EnumValue* enum_value = @@ -819,7 +821,7 @@ Status ProtoStreamObjectSource::RenderField( int old_limit = stream_->PushLimit(buffer32); // Get the nested message type for this field. const google::protobuf::Type* type = - typeinfo_->GetType(field->type_url()); + typeinfo_->GetTypeByTypeUrl(field->type_url()); if (type == NULL) { return Status(util::error::INTERNAL, StrCat("Invalid configuration. Could not find the type: ", @@ -928,7 +930,8 @@ const string ProtoStreamObjectSource::ReadFieldValueAsString( // 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()); + const google::protobuf::Enum* en = + typeinfo_->GetEnumByTypeUrl(field.type_url()); // Lookup the name of the enum, and render that. Skips unknown enums. if (en != NULL) { const google::protobuf::EnumValue* enum_value = @@ -962,7 +965,7 @@ const string ProtoStreamObjectSource::ReadFieldValueAsString( bool ProtoStreamObjectSource::IsMap( const google::protobuf::Field& field) const { const google::protobuf::Type* field_type = - typeinfo_->GetType(field.type_url()); + typeinfo_->GetTypeByTypeUrl(field.type_url()); // TODO(xiaofeng): Unify option names. return field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE && diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h index 4a4e6bbf..845437f5 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource.h +++ b/src/google/protobuf/util/internal/protostream_objectsource.h @@ -46,7 +46,6 @@ #include - namespace google { namespace protobuf { class Field; @@ -61,7 +60,10 @@ 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. +// Its WriteTo() method can be given an ObjectWriter. +// This implementation uses a google.protobuf.Type for tag and name lookup. +// The field names are converted into lower camel-case when writing to the +// ObjectWriter. // // Sample usage: (suppose input is: string proto) // ArrayInputStream arr_stream(proto.data(), proto.size()); @@ -93,7 +95,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { private: ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream, - TypeInfo* typeinfo, + const TypeInfo* typeinfo, const google::protobuf::Type& type); // Function that renders a well known type with a modified behavior. typedef util::Status (*TypeRenderer)(const ProtoStreamObjectSource*, @@ -226,7 +228,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { // Type information for all the types used in the descriptor. Used to find // google::protobuf::Type of nested messages/enums. - TypeInfo* typeinfo_; + const TypeInfo* typeinfo_; // Whether this class owns the typeinfo_ object. If true the typeinfo_ object // should be deleted in the destructor. bool own_typeinfo_; diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc index 4cc62410..f6e5ee7a 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc @@ -117,61 +117,61 @@ class ProtostreamObjectSourceTest void PrepareExpectingObjectWriterForRepeatedPrimitive() { ow_.StartObject("") - ->StartList("rep_fix32") + ->StartList("repFix32") ->RenderUint32("", bit_cast(3201)) ->RenderUint32("", bit_cast(0)) ->RenderUint32("", bit_cast(3202)) ->EndList() - ->StartList("rep_u32") + ->StartList("repU32") ->RenderUint32("", bit_cast(3203)) ->RenderUint32("", bit_cast(0)) ->EndList() - ->StartList("rep_i32") + ->StartList("repI32") ->RenderInt32("", 0) ->RenderInt32("", 3204) ->RenderInt32("", 3205) ->EndList() - ->StartList("rep_sf32") + ->StartList("repSf32") ->RenderInt32("", 3206) ->RenderInt32("", 0) ->EndList() - ->StartList("rep_s32") + ->StartList("repS32") ->RenderInt32("", 0) ->RenderInt32("", 3207) ->RenderInt32("", 3208) ->EndList() - ->StartList("rep_fix64") + ->StartList("repFix64") ->RenderUint64("", bit_cast(6401LL)) ->RenderUint64("", bit_cast(0LL)) ->EndList() - ->StartList("rep_u64") + ->StartList("repU64") ->RenderUint64("", bit_cast(0LL)) ->RenderUint64("", bit_cast(6402LL)) ->RenderUint64("", bit_cast(6403LL)) ->EndList() - ->StartList("rep_i64") + ->StartList("repI64") ->RenderInt64("", 6404L) ->RenderInt64("", 0L) ->EndList() - ->StartList("rep_sf64") + ->StartList("repSf64") ->RenderInt64("", 0L) ->RenderInt64("", 6405L) ->RenderInt64("", 6406L) ->EndList() - ->StartList("rep_s64") + ->StartList("repS64") ->RenderInt64("", 6407L) ->RenderInt64("", 0L) ->EndList() - ->StartList("rep_float") + ->StartList("repFloat") ->RenderFloat("", 0.0f) ->RenderFloat("", 32.1f) ->RenderFloat("", 32.2f) ->EndList() - ->StartList("rep_double") + ->StartList("repDouble") ->RenderDouble("", 64.1L) ->RenderDouble("", 0.0L) ->EndList() - ->StartList("rep_bool") + ->StartList("repBool") ->RenderBool("", true) ->RenderBool("", false) ->EndList() @@ -317,11 +317,11 @@ TEST_P(ProtostreamObjectSourceTest, RepeatingPrimitives) { primitive.add_rep_str("String Two"); primitive.add_rep_bytes("Some Bytes"); - ow_.StartList("rep_str") + ow_.StartList("repStr") ->RenderString("", "String One") ->RenderString("", "String Two") ->EndList() - ->StartList("rep_bytes") + ->StartList("repBytes") ->RenderBytes("", "Some Bytes") ->EndList(); DoTest(primitive, Primitive::descriptor()); @@ -794,16 +794,16 @@ TEST_P(ProtostreamObjectSourceFieldMaskTest, FieldMaskRenderSuccess) { ow_.StartObject("") ->RenderString("id", "1") - ->RenderString("single_mask", "path1,snakeCasePath2") - ->StartList("repeated_mask") + ->RenderString("singleMask", "path1,snakeCasePath2") + ->StartList("repeatedMask") ->RenderString("", "path3") ->RenderString("", "snakeCasePath4,path5") ->EndList() - ->StartList("nested_mask") + ->StartList("nestedMask") ->StartObject("") ->RenderString("data", "data") - ->RenderString("single_mask", "nested.path1,nestedField.snakeCasePath2") - ->StartList("repeated_mask") + ->RenderString("singleMask", "nested.path1,nestedField.snakeCasePath2") + ->StartList("repeatedMask") ->RenderString("", "nestedField.path3,nested.snakeCasePath4") ->RenderString("", "nested.path5") ->RenderString("", diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc index f9ddbf32..87f504e0 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc @@ -74,7 +74,7 @@ ProtoStreamObjectWriter::ProtoStreamObjectWriter( tracker_(new ObjectLocationTracker()) {} ProtoStreamObjectWriter::ProtoStreamObjectWriter( - TypeInfo* typeinfo, const google::protobuf::Type& type, + const TypeInfo* typeinfo, const google::protobuf::Type& type, strings::ByteSink* output, ErrorListener* listener) : master_type_(type), typeinfo_(typeinfo), @@ -91,14 +91,19 @@ ProtoStreamObjectWriter::ProtoStreamObjectWriter( 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_; } + if (element_ == NULL) return; + // Cleanup explicitly in order to avoid destructor stack overflow when input + // is deeply nested. + // Cast to BaseElement to avoid doing additional checks (like missing fields) + // during pop(). + google::protobuf::scoped_ptr element( + static_cast(element_.get())->pop()); + while (element != NULL) { + element.reset(element->pop()); + } } namespace { @@ -454,7 +459,7 @@ void ProtoStreamObjectWriter::AnyWriter::WriteAny() { } ProtoStreamObjectWriter::ProtoElement::ProtoElement( - TypeInfo* typeinfo, const google::protobuf::Type& type, + const TypeInfo* typeinfo, const google::protobuf::Type& type, ProtoStreamObjectWriter* enclosing) : BaseElement(NULL), ow_(enclosing), @@ -586,6 +591,14 @@ string ProtoStreamObjectWriter::ProtoElement::ToString() const { return loc.empty() ? "." : loc; } +bool ProtoStreamObjectWriter::ProtoElement::OneofIndexTaken(int32 index) { + return ContainsKey(oneof_indices_, index); +} + +void ProtoStreamObjectWriter::ProtoElement::TakeOneofIndex(int32 index) { + InsertIfNotPresent(&oneof_indices_, index); +} + inline void ProtoStreamObjectWriter::InvalidName(StringPiece unknown_name, StringPiece message) { listener_->InvalidName(location(), ToSnakeCase(unknown_name), message); @@ -655,6 +668,13 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( return this; } + // Check to see if this field is a oneof and that no oneof in that group has + // already been set. + if (!ValidOneof(*field, name)) { + ++invalid_depth_; + return this; + } + if (field->type_url() == GetFullTypeWithUrl(kStructType)) { // Start a struct object. StartStruct(field); @@ -932,6 +952,14 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) { // Also we ignore if the field is not found here as it is caught later. field = typeinfo_->FindField(&element_->type(), name); + // Only check for oneof collisions on the first StartList call. We identify + // the first call with !name.empty() check. Subsequent list element calls + // will not have the name filled. + if (!name.empty() && field && !ValidOneof(*field, name)) { + ++invalid_depth_; + return this; + } + // 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. @@ -1080,9 +1108,9 @@ Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow, 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. +// 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 > callback( NewPermanentCallback(&RenderOneFieldPath, ow)); return DecodeCompactFieldMaskPaths(data.str(), callback.get()); @@ -1154,6 +1182,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece( const google::protobuf::Field* field = NULL; string type_url; bool is_map_entry = false; + // We are at the root when element_ == NULL. if (element_ == NULL) { type_url = GetFullTypeWithUrl(master_type_.name()); } else { @@ -1166,6 +1195,11 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece( if (field == NULL) { return this; } + + // Check to see if this field is a oneof and that no oneof in that group has + // already been set. + if (!ValidOneof(*field, name)) return this; + type_url = field->type_url(); } @@ -1314,7 +1348,8 @@ void ProtoStreamObjectWriter::RenderSimpleDataPiece( } case google::protobuf::Field_Kind_TYPE_ENUM: { status = WriteEnum(field.number(), data, - typeinfo_->GetEnum(field.type_url()), stream_.get()); + typeinfo_->GetEnumByTypeUrl(field.type_url()), + stream_.get()); break; } default: // TYPE_GROUP or TYPE_MESSAGE @@ -1401,6 +1436,24 @@ ProtoStreamObjectWriter::GetElementType(const google::protobuf::Type& type) { } } +bool ProtoStreamObjectWriter::ValidOneof(const google::protobuf::Field& field, + StringPiece unnormalized_name) { + if (element_ == NULL) return true; + + if (field.oneof_index() > 0) { + if (element_->OneofIndexTaken(field.oneof_index())) { + InvalidValue( + "oneof", + StrCat("oneof field '", + element_->type().oneofs(field.oneof_index() - 1), + "' is already set. Cannot set '", unnormalized_name, "'")); + return false; + } + element_->TakeOneofIndex(field.oneof_index()); + } + return true; +} + const google::protobuf::Field* ProtoStreamObjectWriter::BeginNamed( StringPiece name, bool is_list) { if (invalid_depth_ > 0) { @@ -1450,7 +1503,7 @@ const google::protobuf::Field* ProtoStreamObjectWriter::Lookup( 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()) + ? typeinfo_->GetTypeByTypeUrl(field->type_url()) : &element_->type()); } @@ -1539,7 +1592,7 @@ bool ProtoStreamObjectWriter::IsMap(const google::protobuf::Field& field) { return false; } const google::protobuf::Type* field_type = - typeinfo_->GetType(field.type_url()); + typeinfo_->GetTypeByTypeUrl(field.type_url()); return GetBoolOptionOrDefault(field_type->options(), "google.protobuf.MessageOptions.map_entry", false); diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h index eb4a59f9..f11c47c0 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.h +++ b/src/google/protobuf/util/internal/protostream_objectwriter.h @@ -71,7 +71,7 @@ class ObjectLocationTracker; // It also supports streaming. class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter { public: - // Constructor. Does not take ownership of any parameter passed in. +// Constructor. Does not take ownership of any parameter passed in. ProtoStreamObjectWriter(TypeResolver* type_resolver, const google::protobuf::Type& type, strings::ByteSink* output, ErrorListener* listener); @@ -82,20 +82,17 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter virtual ProtoStreamObjectWriter* EndObject(); virtual ProtoStreamObjectWriter* StartList(StringPiece name); virtual ProtoStreamObjectWriter* EndList(); - virtual ProtoStreamObjectWriter* RenderBool(StringPiece name, - bool value) { + virtual ProtoStreamObjectWriter* RenderBool(StringPiece name, bool value) { return RenderDataPiece(name, DataPiece(value)); } - virtual ProtoStreamObjectWriter* RenderInt32(StringPiece name, - int32 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) { + virtual ProtoStreamObjectWriter* RenderInt64(StringPiece name, int64 value) { return RenderDataPiece(name, DataPiece(value)); } virtual ProtoStreamObjectWriter* RenderUint64(StringPiece name, @@ -106,8 +103,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter double value) { return RenderDataPiece(name, DataPiece(value)); } - virtual ProtoStreamObjectWriter* RenderFloat(StringPiece name, - float value) { + virtual ProtoStreamObjectWriter* RenderFloat(StringPiece name, float value) { return RenderDataPiece(name, DataPiece(value)); } virtual ProtoStreamObjectWriter* RenderString(StringPiece name, @@ -217,7 +213,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter }; // Constructor for the root element. No parent nor field. - ProtoElement(TypeInfo* typeinfo, const google::protobuf::Type& type, + ProtoElement(const TypeInfo* typeinfo, const google::protobuf::Type& type, ProtoStreamObjectWriter* enclosing); // Constructor for a field of an element. @@ -256,6 +252,13 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter return static_cast(BaseElement::parent()); } + // Returns true if the index is already taken by a preceeding oneof input. + bool OneofIndexTaken(int32 index); + + // Marks the oneof 'index' as taken. Future inputs to this oneof will + // generate an error. + void TakeOneofIndex(int32 index); + private: // Used for access to variables of the enclosing instance of // ProtoStreamObjectWriter. @@ -269,7 +272,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter const google::protobuf::Field* field_; // TypeInfo to lookup types. - TypeInfo* typeinfo_; + const TypeInfo* typeinfo_; // Additional variables if this element is a message: // (Root element is always a message). @@ -289,6 +292,10 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter // The type of this element, see enum for permissible types. ElementType element_type_; + // Set of oneof indices already seen for the type_. Used to validate + // incoming messages so no more than one oneof is set. + hash_set oneof_indices_; + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoElement); }; @@ -298,7 +305,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter int size; }; - ProtoStreamObjectWriter(TypeInfo* typeinfo, + ProtoStreamObjectWriter(const TypeInfo* typeinfo, const google::protobuf::Type& type, strings::ByteSink* output, ErrorListener* listener); @@ -407,11 +414,19 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter static ProtoElement::ElementType GetElementType( const google::protobuf::Type& type); + // Returns true if the field for type_ can be set as a oneof. If field is not + // a oneof type, this function does nothing and returns true. + // If another field for this oneof is already set, this function returns + // false. It also calls the appropriate error callback. + // unnormalized_name is used for error string. + bool ValidOneof(const google::protobuf::Field& field, + StringPiece unnormalized_name); + // 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_; + const TypeInfo* typeinfo_; // Whether we own the typeinfo_ object. bool own_typeinfo_; diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc index bd4f29f5..96e5ccfb 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -75,6 +76,7 @@ using ::testing::_; using ::testing::Args; using google::protobuf::testing::anys::AnyM; using google::protobuf::testing::anys::AnyOut; +using google::protobuf::testing::oneofs::OneOfsRequest; using google::protobuf::testing::FieldMaskTest; using google::protobuf::testing::maps::MapIn; using google::protobuf::testing::structs::StructType; @@ -143,7 +145,7 @@ class BaseProtoStreamObjectWriterTest void CheckOutput(const Message& expected) { CheckOutput(expected, -1); } const google::protobuf::Type* GetType(const Descriptor* descriptor) { - return helper_.GetTypeInfo()->GetType(GetTypeUrl(descriptor)); + return helper_.GetTypeInfo()->GetTypeByTypeUrl(GetTypeUrl(descriptor)); } testing::TypeInfoTestHelper helper_; @@ -854,11 +856,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError1) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece( - "Field 'ts', Illegal timestamp format; timestamps " - "must end with 'Z'"))); + 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); @@ -883,11 +884,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError3) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece( - "Field 'ts', Invalid time format, failed to parse nano " - "seconds"))); + 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") @@ -919,11 +919,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError1) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Duration"), - StringPiece( - "Field 'dur', Illegal duration format; duration must " - "end with 's'"))); + 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); @@ -934,11 +933,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError2) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Duration"), - StringPiece( - "Field 'dur', Invalid duration format, failed to parse " - "seconds"))); + 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); @@ -949,11 +947,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError3) { EXPECT_CALL( listener_, - InvalidValue(_, - StringPiece("type.googleapis.com/google.protobuf.Duration"), - StringPiece( - "Field 'dur', Invalid duration format, failed to " - "parse nanos seconds"))); + 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); @@ -1174,10 +1171,10 @@ TEST_P(ProtoStreamObjectWriterAnyTest, EmptyAnyFromEmptyObject) { TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) { AnyOut any; - EXPECT_CALL(listener_, - InvalidValue(_, StringPiece("Any"), - StringPiece( - "Missing or invalid @type for any field in " + EXPECT_CALL( + listener_, + InvalidValue(_, StringPiece("Any"), + StringPiece("Missing or invalid @type for any field in " "google.protobuf.testing.anys.AnyOut"))); ow_->StartObject("") @@ -1192,10 +1189,10 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) { TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) { AnyOut any; - EXPECT_CALL(listener_, - InvalidValue(_, StringPiece("Any"), - StringPiece( - "Missing or invalid @type for any field in " + EXPECT_CALL( + listener_, + InvalidValue(_, StringPiece("Any"), + StringPiece("Missing or invalid @type for any field in " "google.protobuf.testing.anys.AnyOut"))); ow_->StartObject("") @@ -1210,10 +1207,10 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) { TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails3) { AnyOut any; - EXPECT_CALL(listener_, - InvalidValue(_, StringPiece("Any"), - StringPiece( - "Missing or invalid @type for any field in " + EXPECT_CALL( + listener_, + InvalidValue(_, StringPiece("Any"), + StringPiece("Missing or invalid @type for any field in " "google.protobuf.testing.anys.AnyOut"))); ow_->StartObject("") @@ -1227,13 +1224,12 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails3) { 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/', got: " - "type.other.com/some.Type"))); + EXPECT_CALL(listener_, + InvalidValue( + _, StringPiece("Any"), + StringPiece("Invalid type URL, type URLs must be of the form " + "'type.googleapis.com/', got: " + "type.other.com/some.Type"))); ow_->StartObject("") ->StartObject("any") @@ -1401,11 +1397,10 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, MaskUsingApiaryStyleShouldWork) { 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 ')'."))); + 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"); @@ -1448,12 +1443,11 @@ 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."))); + 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", @@ -1466,10 +1460,9 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustEnd) { 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\"]."))); + 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\""); @@ -1481,10 +1474,9 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustBeEscapedCorrectly) { 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\"]."))); + 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\"]"); @@ -1507,6 +1499,192 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyCanContainAnyChars) { CheckOutput(expected); } +class ProtoStreamObjectWriterOneOfsTest + : public BaseProtoStreamObjectWriterTest { + protected: + ProtoStreamObjectWriterOneOfsTest() { + vector descriptors; + descriptors.push_back(OneOfsRequest::descriptor()); + descriptors.push_back(google::protobuf::Struct::descriptor()); + ResetTypeInfo(descriptors); + } +}; + +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtoStreamObjectWriterOneOfsTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + +TEST_P(ProtoStreamObjectWriterOneOfsTest, + MultipleOneofsFailForPrimitiveTypesTest) { + EXPECT_CALL( + listener_, + InvalidValue( + _, StringPiece("oneof"), + StringPiece( + "oneof field 'data' is already set. Cannot set 'intData'"))); + + ow_->StartObject(""); + ow_->RenderString("strData", "blah"); + ow_->RenderString("intData", "123"); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterOneOfsTest, + MultipleOneofsFailForMessageTypesPrimitiveFirstTest) { + // Test for setting primitive oneof field first and then message field. + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("oneof"), + StringPiece("oneof field 'data' is already set. " + "Cannot set 'messageData'"))); + + // JSON: { "strData": "blah", "messageData": { "dataValue": 123 } } + ow_->StartObject(""); + ow_->RenderString("strData", "blah"); + ow_->StartObject("messageData"); + ow_->RenderInt32("dataValue", 123); + ow_->EndObject(); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterOneOfsTest, + MultipleOneofsFailForMessageTypesMessageFirstTest) { + // Test for setting message oneof field first and then primitive field. + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("oneof"), + StringPiece("oneof field 'data' is already set. " + "Cannot set 'strData'"))); + + // JSON: { "messageData": { "dataValue": 123 }, "strData": "blah" } + ow_->StartObject(""); + ow_->StartObject("messageData"); + ow_->RenderInt32("dataValue", 123); + ow_->EndObject(); + ow_->RenderString("strData", "blah"); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterOneOfsTest, + MultipleOneofsFailForStructTypesPrimitiveFirstTest) { + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("oneof"), + StringPiece("oneof field 'data' is already set. " + "Cannot set 'structData'"))); + + // JSON: { "strData": "blah", "structData": { "a": "b" } } + ow_->StartObject(""); + ow_->RenderString("strData", "blah"); + ow_->StartObject("structData"); + ow_->RenderString("a", "b"); + ow_->EndObject(); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterOneOfsTest, + MultipleOneofsFailForStructTypesStructFirstTest) { + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("oneof"), + StringPiece("oneof field 'data' is already set. " + "Cannot set 'strData'"))); + + // JSON: { "structData": { "a": "b" }, "strData": "blah" } + ow_->StartObject(""); + ow_->StartObject("structData"); + ow_->RenderString("a", "b"); + ow_->EndObject(); + ow_->RenderString("strData", "blah"); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterOneOfsTest, + MultipleOneofsFailForStructValueTypesTest) { + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("oneof"), + StringPiece("oneof field 'data' is already set. " + "Cannot set 'valueData'"))); + + // JSON: { "messageData": { "dataValue": 123 }, "valueData": { "a": "b" } } + ow_->StartObject(""); + ow_->StartObject("messageData"); + ow_->RenderInt32("dataValue", 123); + ow_->EndObject(); + ow_->StartObject("valueData"); + ow_->RenderString("a", "b"); + ow_->EndObject(); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterOneOfsTest, + MultipleOneofsFailForWellKnownTypesPrimitiveFirstTest) { + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("oneof"), + StringPiece("oneof field 'data' is already set. " + "Cannot set 'tsData'"))); + + // JSON: { "intData": 123, "tsData": "1970-01-02T01:00:00.000Z" } + ow_->StartObject(""); + ow_->RenderInt32("intData", 123); + ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z"); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterOneOfsTest, + MultipleOneofsFailForWellKnownTypesWktFirstTest) { + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("oneof"), + StringPiece("oneof field 'data' is already set. " + "Cannot set 'intData'"))); + + // JSON: { "tsData": "1970-01-02T01:00:00.000Z", "intData": 123 } + ow_->StartObject(""); + ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z"); + ow_->RenderInt32("intData", 123); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterOneOfsTest, + MultipleOneofsFailForWellKnownTypesAndMessageTest) { + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("oneof"), + StringPiece("oneof field 'data' is already set. " + "Cannot set 'messageData'"))); + + // JSON: { "tsData": "1970-01-02T01:00:00.000Z", + // "messageData": { "dataValue": 123 } } + ow_->StartObject(""); + ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z"); + ow_->StartObject("messageData"); + ow_->RenderInt32("dataValue", 123); + ow_->EndObject(); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterOneOfsTest, + MultipleOneofsFailForOneofWithinAnyTest) { + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("oneof"), + StringPiece("oneof field 'data' is already set. " + "Cannot set 'intData'"))); + + using google::protobuf::testing::oneofs::OneOfsRequest; + // JSON: + // { "anyData": + // { "@type": + // "type.googleapis.com/google.protobuf.testing.oneofs.OneOfsRequest", + // "strData": "blah", + // "intData": 123 + // } + // } + ow_->StartObject(""); + ow_->StartObject("anyData"); + ow_->RenderString( + "@type", + "type.googleapis.com/google.protobuf.testing.oneofs.OneOfsRequest"); + ow_->RenderString("strData", "blah"); + ow_->RenderInt32("intData", 123); + ow_->EndObject(); +} + } // namespace converter } // namespace util } // namespace protobuf diff --git a/src/google/protobuf/util/internal/snake2camel_objectwriter.h b/src/google/protobuf/util/internal/snake2camel_objectwriter.h index 1a32bc56..9b4ab8a3 100644 --- a/src/google/protobuf/util/internal/snake2camel_objectwriter.h +++ b/src/google/protobuf/util/internal/snake2camel_objectwriter.h @@ -58,9 +58,7 @@ class Snake2CamelObjectWriter : public ObjectWriter { // ObjectWriter methods. virtual Snake2CamelObjectWriter* StartObject(StringPiece name) { - ow_->StartObject(ShouldNormalizeCase(name) - ? StringPiece(StringPiece(ToCamelCase(name))) - : name); + ow_->StartObject(name); return this; } @@ -70,8 +68,7 @@ class Snake2CamelObjectWriter : public ObjectWriter { } virtual Snake2CamelObjectWriter* StartList(StringPiece name) { - ow_->StartList(ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) - : name); + ow_->StartList(name); return this; } @@ -81,76 +78,57 @@ class Snake2CamelObjectWriter : public ObjectWriter { } virtual Snake2CamelObjectWriter* RenderBool(StringPiece name, bool value) { - ow_->RenderBool( - ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, - value); + ow_->RenderBool(name, value); return this; } virtual Snake2CamelObjectWriter* RenderInt32(StringPiece name, int32 value) { - ow_->RenderInt32( - ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, - value); + ow_->RenderInt32(name, value); return this; } virtual Snake2CamelObjectWriter* RenderUint32(StringPiece name, uint32 value) { - ow_->RenderUint32( - ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, - value); + ow_->RenderUint32(name, value); return this; } virtual Snake2CamelObjectWriter* RenderInt64(StringPiece name, int64 value) { - ow_->RenderInt64( - ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, - value); + ow_->RenderInt64(name, value); return this; } virtual Snake2CamelObjectWriter* RenderUint64(StringPiece name, uint64 value) { - ow_->RenderUint64( - ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, - value); + ow_->RenderUint64(name, value); return this; } virtual Snake2CamelObjectWriter* RenderDouble(StringPiece name, double value) { - ow_->RenderDouble( - ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, - value); + ow_->RenderDouble(name, value); return this; } virtual Snake2CamelObjectWriter* RenderFloat(StringPiece name, float value) { - ow_->RenderFloat( - ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, - value); + ow_->RenderFloat(name, value); return this; } virtual Snake2CamelObjectWriter* RenderString(StringPiece name, StringPiece value) { - ow_->RenderString( - ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, - value); + ow_->RenderString(name, value); return this; } virtual Snake2CamelObjectWriter* RenderBytes(StringPiece name, StringPiece value) { - ow_->RenderBytes( - ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, - value); + ow_->RenderBytes(name, value); return this; } virtual Snake2CamelObjectWriter* RenderNull(StringPiece name) { - ow_->RenderNull(ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) - : name); + ow_->RenderNull(name); return this; } diff --git a/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc b/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc index 67388c3b..e5db844c 100644 --- a/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc +++ b/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc @@ -47,263 +47,9 @@ class Snake2CamelObjectWriterTest : public ::testing::Test { 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(); -} +// All tests are deleted as they are no longer needed. This file will be removed +// after the component dependecies are cleaned up. +// TODO(skarvaje): Remove this file. } // namespace converter } // namespace util diff --git a/src/google/protobuf/util/internal/testdata/default_value.proto b/src/google/protobuf/util/internal/testdata/default_value.proto index ecfc8119..ebbdf6ab 100644 --- a/src/google/protobuf/util/internal/testdata/default_value.proto +++ b/src/google/protobuf/util/internal/testdata/default_value.proto @@ -43,6 +43,7 @@ message DefaultValueTestCases { DoubleMessage repeated_double = 4; DoubleMessage nested_message = 5; DoubleMessage repeated_nested_message = 6; + DoubleMessage double_message_with_oneof = 7; StructMessage empty_struct = 201; StructMessage empty_struct2 = 202; StructMessage struct_with_null_value = 203; @@ -75,6 +76,8 @@ message DefaultValueTestCases { MixedMap mixed1 = 404; MixedMap2 mixed2 = 405; MessageMap map_of_objects = 406; + MixedMap mixed_empty = 407; + MessageMap message_map_empty = 408; DoubleValueMessage double_value = 501; DoubleValueMessage double_value_default = 502; } @@ -85,6 +88,10 @@ message DoubleMessage { DoubleMessage nested_message = 3; repeated DoubleMessage repeated_nested_message = 4; google.protobuf.DoubleValue double_wrapper = 100; + oneof value { + string str_value = 112; + int64 num_value = 113; + } } message StructMessage { diff --git a/src/google/protobuf/util/internal/type_info.cc b/src/google/protobuf/util/internal/type_info.cc index 6392e18c..a45a76e3 100644 --- a/src/google/protobuf/util/internal/type_info.cc +++ b/src/google/protobuf/util/internal/type_info.cc @@ -35,11 +35,11 @@ #include #include +#include #include #include #include #include -#include namespace google { namespace protobuf { @@ -47,7 +47,6 @@ namespace util { namespace converter { namespace { - // A TypeInfo that looks up information provided by a TypeResolver. class TypeInfoForTypeResolver : public TypeInfo { public: @@ -60,7 +59,7 @@ class TypeInfoForTypeResolver : public TypeInfo { } virtual util::StatusOr ResolveTypeUrl( - StringPiece type_url) { + StringPiece type_url) const { map::iterator it = cached_types_.find(type_url); if (it != cached_types_.end()) { return it->second; @@ -78,12 +77,14 @@ class TypeInfoForTypeResolver : public TypeInfo { return result; } - virtual const google::protobuf::Type* GetType(StringPiece type_url) { + virtual const google::protobuf::Type* GetTypeByTypeUrl( + StringPiece type_url) const { StatusOrType result = ResolveTypeUrl(type_url); return result.ok() ? result.ValueOrDie() : NULL; } - virtual const google::protobuf::Enum* GetEnum(StringPiece type_url) { + virtual const google::protobuf::Enum* GetEnumByTypeUrl( + StringPiece type_url) const { map::iterator it = cached_enums_.find(type_url); if (it != cached_enums_.end()) { return it->second.ok() ? it->second.ValueOrDie() : NULL; @@ -103,7 +104,7 @@ class TypeInfoForTypeResolver : public TypeInfo { } virtual const google::protobuf::Field* FindField( - const google::protobuf::Type* type, StringPiece camel_case_name) { + const google::protobuf::Type* type, StringPiece camel_case_name) const { if (indexed_types_.find(type) == indexed_types_.end()) { PopulateNameLookupTable(type); indexed_types_.insert(type); @@ -131,7 +132,7 @@ class TypeInfoForTypeResolver : public TypeInfo { } } - void PopulateNameLookupTable(const google::protobuf::Type* type) { + void PopulateNameLookupTable(const google::protobuf::Type* type) const { for (int i = 0; i < type->fields_size(); ++i) { const google::protobuf::Field& field = type->fields(i); StringPiece name = field.name(); @@ -151,13 +152,13 @@ class TypeInfoForTypeResolver : public TypeInfo { // Stores string values that will be referenced by StringPieces in // cached_types_, cached_enums_ and camel_case_name_table_. - set string_storage_; + mutable set string_storage_; - map cached_types_; - map cached_enums_; + mutable map cached_types_; + mutable map cached_enums_; - set indexed_types_; - map camel_case_name_table_; + mutable set indexed_types_; + mutable map camel_case_name_table_; }; } // namespace diff --git a/src/google/protobuf/util/internal/type_info.h b/src/google/protobuf/util/internal/type_info.h index 67403fff..e394e8cf 100644 --- a/src/google/protobuf/util/internal/type_info.h +++ b/src/google/protobuf/util/internal/type_info.h @@ -44,7 +44,7 @@ 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 { +class TypeInfo { public: TypeInfo() {} virtual ~TypeInfo() {} @@ -55,24 +55,29 @@ class LIBPROTOBUF_EXPORT TypeInfo { // // This TypeInfo class retains the ownership of the returned pointer. virtual util::StatusOr ResolveTypeUrl( - StringPiece type_url) = 0; + StringPiece type_url) const = 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; + virtual const google::protobuf::Type* GetTypeByTypeUrl( + StringPiece type_url) const = 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; + virtual const google::protobuf::Enum* GetEnumByTypeUrl( + StringPiece type_url) const = 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; + const google::protobuf::Type* type, + StringPiece camel_case_name) const = 0; + // Creates a TypeInfo object that looks up type information from a + // TypeResolver. Caller takes ownership of the returned pointer. static TypeInfo* NewTypeInfo(TypeResolver* type_resolver); private: diff --git a/src/google/protobuf/util/internal/type_info_test_helper.cc b/src/google/protobuf/util/internal/type_info_test_helper.cc index 177b96e2..1b9c5154 100644 --- a/src/google/protobuf/util/internal/type_info_test_helper.cc +++ b/src/google/protobuf/util/internal/type_info_test_helper.cc @@ -36,6 +36,7 @@ #endif #include +#include #include #include #include @@ -89,7 +90,7 @@ 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); + const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url); switch (type_) { case USE_TYPE_RESOLVER: { return new ProtoStreamObjectSource(coded_input, type_resolver_.get(), @@ -103,7 +104,7 @@ ProtoStreamObjectSource* TypeInfoTestHelper::NewProtoSource( ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter( const string& type_url, strings::ByteSink* output, ErrorListener* listener) { - const google::protobuf::Type* type = typeinfo_->GetType(type_url); + const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url); switch (type_) { case USE_TYPE_RESOLVER: { return new ProtoStreamObjectWriter(type_resolver_.get(), *type, output, @@ -116,7 +117,7 @@ ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter( DefaultValueObjectWriter* TypeInfoTestHelper::NewDefaultValueWriter( const string& type_url, ObjectWriter* writer) { - const google::protobuf::Type* type = typeinfo_->GetType(type_url); + const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url); switch (type_) { case USE_TYPE_RESOLVER: { return new DefaultValueObjectWriter(type_resolver_.get(), *type, writer); diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc index 794777d4..2d63de00 100644 --- a/src/google/protobuf/util/internal/utility.cc +++ b/src/google/protobuf/util/internal/utility.cc @@ -34,7 +34,9 @@ #include #include +#include #include +#include #include #include #include @@ -303,7 +305,7 @@ bool IsMap(const google::protobuf::Field& field, string DoubleAsString(double value) { if (value == std::numeric_limits::infinity()) return "Infinity"; if (value == -std::numeric_limits::infinity()) return "-Infinity"; - if (google::protobuf::MathLimits::IsNaN(value)) return "NaN"; + if (MathLimits::IsNaN(value)) return "NaN"; return SimpleDtoa(value); } diff --git a/src/google/protobuf/util/internal/utility.h b/src/google/protobuf/util/internal/utility.h index d0d88c19..87f7602a 100644 --- a/src/google/protobuf/util/internal/utility.h +++ b/src/google/protobuf/util/internal/utility.h @@ -39,6 +39,7 @@ #include #include +#include #include #include #include @@ -117,23 +118,23 @@ 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::Option* FindOptionOrNull( const google::protobuf::RepeatedPtrField& 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::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::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::EnumValue* FindEnumValueByNumberOrNull( const google::protobuf::Enum* enum_type, int32 value); // Converts input to camel-case and returns it. @@ -153,7 +154,7 @@ LIBPROTOBUF_EXPORT bool IsWellKnownType(const string& type_name); 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, +LIBPROTOBUF_EXPORT bool IsMap(const google::protobuf::Field& field, const google::protobuf::Type& type); // Infinity/NaN-aware conversion to string. diff --git a/src/google/protobuf/util/json_util.h b/src/google/protobuf/util/json_util.h index 6796ea08..614564cc 100644 --- a/src/google/protobuf/util/json_util.h +++ b/src/google/protobuf/util/json_util.h @@ -44,7 +44,7 @@ class ZeroCopyOutputStream; } // namespace io namespace util { -struct LIBPROTOBUF_EXPORT JsonOptions { +struct JsonOptions { // Whether to add spaces, line breaks and indentation to make the JSON output // easy to read. bool add_whitespace; @@ -65,7 +65,7 @@ struct LIBPROTOBUF_EXPORT JsonOptions { // 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( +util::Status BinaryToJsonStream( TypeResolver* resolver, const string& type_url, io::ZeroCopyInputStream* binary_input, @@ -80,7 +80,7 @@ inline util::Status BinaryToJsonStream( JsonOptions()); } -LIBPROTOBUF_EXPORT util::Status BinaryToJsonString( +util::Status BinaryToJsonString( TypeResolver* resolver, const string& type_url, const string& binary_input, @@ -101,13 +101,13 @@ inline util::Status BinaryToJsonString(TypeResolver* resolver, // 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( +util::Status JsonToBinaryStream( TypeResolver* resolver, const string& type_url, io::ZeroCopyInputStream* json_input, io::ZeroCopyOutputStream* binary_output); -LIBPROTOBUF_EXPORT util::Status JsonToBinaryString( +util::Status JsonToBinaryString( TypeResolver* resolver, const string& type_url, const string& json_input, diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc index 8399b408..7f88e672 100644 --- a/src/google/protobuf/util/json_util_test.cc +++ b/src/google/protobuf/util/json_util_test.cc @@ -98,27 +98,28 @@ TEST_F(JsonUtilTest, TestWhitespaces) { 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)); -} +// TODO(skarvaje): Uncomment after cl/96232915 is submitted. +// TEST_F(JsonUtilTest, TestDefaultValues) { + // TestMessage m; + // JsonOptions options; + // EXPECT_EQ("{}", ToJson(m, options)); + // options.always_print_primitive_fields = true; + // EXPECT_EQ( + // "{\"boolValue\":false," + // "\"int32Value\":0," + // "\"int64Value\":\"0\"," + // "\"uint32Value\":0," + // "\"uint64Value\":\"0\"," + // "\"floatValue\":0," + // "\"doubleValue\":0," + // "\"stringValue\":\"\"," + // "\"bytesValue\":\"\"," + // // TODO(xiaofeng): The default enum value should be FOO. I believe + // // this is a bug in DefaultValueObjectWriter. + // "\"enumValue\":null" + // "}", + // ToJson(m, options)); +// } TEST_F(JsonUtilTest, ParseMessage) { // Some random message but good enough to verify that the parsing warpper diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc index 057b414a..d709da57 100644 --- a/src/google/protobuf/util/message_differencer.cc +++ b/src/google/protobuf/util/message_differencer.cc @@ -45,6 +45,7 @@ #endif #include +#include #include #include #include diff --git a/src/google/protobuf/util/message_differencer_unittest.cc b/src/google/protobuf/util/message_differencer_unittest.cc index bd19f695..701b94ae 100755 --- a/src/google/protobuf/util/message_differencer_unittest.cc +++ b/src/google/protobuf/util/message_differencer_unittest.cc @@ -52,6 +52,7 @@ #include #include +#include #include #include #include @@ -131,7 +132,7 @@ TEST(MessageDifferencerTest, MapFieldEqualityTest) { unittest::TestMap msg1; unittest::TestMap msg2; - MapTestUtil::MapReflectionTester tester(unittest::TestMap::descriptor()); + MapReflectionTester tester(unittest::TestMap::descriptor()); tester.SetMapFieldsViaReflection(&msg1); tester.SetMapFieldsViaReflection(&msg2); tester.SwapMapsViaReflection(&msg1); diff --git a/src/google/protobuf/util/type_resolver_util.cc b/src/google/protobuf/util/type_resolver_util.cc index 053a4ed7..908634eb 100644 --- a/src/google/protobuf/util/type_resolver_util.cc +++ b/src/google/protobuf/util/type_resolver_util.cc @@ -35,6 +35,7 @@ #include #include #include +#include #include namespace google { @@ -64,6 +65,47 @@ bool SplitTypeUrl(const string& type_url, return true; } +// This code is originally defined in +// //google/protobuf/util/converter/utility.h. Copied here due to component +// dependency. +// TODO(xiaofeng): Remove this when converter code is in components. +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; +} class DescriptorPoolTypeResolver : public TypeResolver { public: @@ -155,6 +197,7 @@ class DescriptorPoolTypeResolver : public TypeResolver { } field->set_number(descriptor->number()); field->set_name(descriptor->name()); + field->set_json_name(ToCamelCase(descriptor->name())); if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE) { field->set_type_url(GetTypeUrl(descriptor->message_type())); } else if (descriptor->type() == FieldDescriptor::TYPE_ENUM) { diff --git a/src/google/protobuf/util/type_resolver_util.h b/src/google/protobuf/util/type_resolver_util.h index c0ef3c1a..00cf9c13 100644 --- a/src/google/protobuf/util/type_resolver_util.h +++ b/src/google/protobuf/util/type_resolver_util.h @@ -42,7 +42,7 @@ 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( +TypeResolver* NewTypeResolverForDescriptorPool( const string& url_prefix, const DescriptorPool* pool); } // namespace util diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc index c5db963b..8fbd116b 100644 --- a/src/google/protobuf/wire_format.cc +++ b/src/google/protobuf/wire_format.cc @@ -38,6 +38,7 @@ #include +#include #include #include #include diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc index 2ce4920c..dade41af 100644 --- a/src/google/protobuf/wire_format_lite.cc +++ b/src/google/protobuf/wire_format_lite.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -484,9 +485,9 @@ void WireFormatLite::WriteMessageMaybeToArray(int field_number, } } -static inline bool ReadBytesToString(io::CodedInputStream* input, - string* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; -static inline bool ReadBytesToString(io::CodedInputStream* input, +GOOGLE_ATTRIBUTE_ALWAYS_INLINE static bool ReadBytesToString( + io::CodedInputStream* input, string* value); +inline static bool ReadBytesToString(io::CodedInputStream* input, string* value) { uint32 length; return input->ReadVarint32(&length) && diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h index ac83abdc..19fbc2c5 100644 --- a/src/google/protobuf/wire_format_lite.h +++ b/src/google/protobuf/wire_format_lite.h @@ -250,17 +250,17 @@ class LIBPROTOBUF_EXPORT WireFormatLite { // For primitive fields, we just use a templatized routine parameterized by // the represented type and the FieldType. These are specialized with the // appropriate definition for each declared type. - template - static inline bool ReadPrimitive(input, CType* value) INL; + template INL + static bool ReadPrimitive(input, CType* value); // Reads repeated primitive values, with optimizations for repeats. // tag_size and tag should both be compile-time constants provided by the // protocol compiler. - template - static inline bool ReadRepeatedPrimitive(int tag_size, - uint32 tag, - input, - RepeatedField* value) INL; + template INL + static bool ReadRepeatedPrimitive(int tag_size, + uint32 tag, + input, + RepeatedField* value); // Identical to ReadRepeatedPrimitive, except will not inline the // implementation. @@ -275,16 +275,14 @@ class LIBPROTOBUF_EXPORT WireFormatLite { // // This is only implemented for the types with fixed wire size, e.g. // float, double, and the (s)fixed* types. - template - static inline const uint8* ReadPrimitiveFromArray(const uint8* buffer, - CType* value) INL; + template INL + static const uint8* ReadPrimitiveFromArray(const uint8* buffer, CType* value); // Reads a primitive packed field. // // This is only implemented for packable types. - template - static inline bool ReadPackedPrimitive(input, - RepeatedField* value) INL; + template INL + static bool ReadPackedPrimitive(input, RepeatedField* value); // Identical to ReadPackedPrimitive, except will not inline the // implementation. @@ -344,23 +342,23 @@ class LIBPROTOBUF_EXPORT WireFormatLite { // 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. - static inline void WriteTag(field_number, WireType type, output) INL; + INL static void WriteTag(field_number, WireType type, output); // Write fields, without tags. - static inline void WriteInt32NoTag (int32 value, output) INL; - static inline void WriteInt64NoTag (int64 value, output) INL; - static inline void WriteUInt32NoTag (uint32 value, output) INL; - static inline void WriteUInt64NoTag (uint64 value, output) INL; - static inline void WriteSInt32NoTag (int32 value, output) INL; - static inline void WriteSInt64NoTag (int64 value, output) INL; - static inline void WriteFixed32NoTag (uint32 value, output) INL; - static inline void WriteFixed64NoTag (uint64 value, output) INL; - static inline void WriteSFixed32NoTag(int32 value, output) INL; - static inline void WriteSFixed64NoTag(int64 value, output) INL; - static inline void WriteFloatNoTag (float value, output) INL; - static inline void WriteDoubleNoTag (double value, output) INL; - static inline void WriteBoolNoTag (bool value, output) INL; - static inline void WriteEnumNoTag (int value, output) INL; + INL static void WriteInt32NoTag (int32 value, output); + INL static void WriteInt64NoTag (int64 value, output); + INL static void WriteUInt32NoTag (uint32 value, output); + INL static void WriteUInt64NoTag (uint64 value, output); + INL static void WriteSInt32NoTag (int32 value, output); + INL static void WriteSInt64NoTag (int64 value, output); + INL static void WriteFixed32NoTag (uint32 value, output); + INL static void WriteFixed64NoTag (uint64 value, output); + INL static void WriteSFixed32NoTag(int32 value, output); + INL static void WriteSFixed64NoTag(int64 value, output); + INL static void WriteFloatNoTag (float value, output); + INL static void WriteDoubleNoTag (double value, output); + INL static void WriteBoolNoTag (bool value, output); + INL static void WriteEnumNoTag (int value, output); // Write fields, including tags. static void WriteInt32 (field_number, int32 value, output); @@ -410,73 +408,59 @@ class LIBPROTOBUF_EXPORT WireFormatLite { #define output uint8* target // Like above, but use only *ToArray methods of CodedOutputStream. - static inline uint8* WriteTagToArray(field_number, WireType type, output) INL; + INL static uint8* WriteTagToArray(field_number, WireType type, output); // Write fields, without tags. - static inline uint8* WriteInt32NoTagToArray (int32 value, output) INL; - static inline uint8* WriteInt64NoTagToArray (int64 value, output) INL; - static inline uint8* WriteUInt32NoTagToArray (uint32 value, output) INL; - static inline uint8* WriteUInt64NoTagToArray (uint64 value, output) INL; - static inline uint8* WriteSInt32NoTagToArray (int32 value, output) INL; - static inline uint8* WriteSInt64NoTagToArray (int64 value, output) INL; - static inline uint8* WriteFixed32NoTagToArray (uint32 value, output) INL; - static inline uint8* WriteFixed64NoTagToArray (uint64 value, output) INL; - static inline uint8* WriteSFixed32NoTagToArray(int32 value, output) INL; - static inline uint8* WriteSFixed64NoTagToArray(int64 value, output) INL; - static inline uint8* WriteFloatNoTagToArray (float value, output) INL; - static inline uint8* WriteDoubleNoTagToArray (double value, output) INL; - static inline uint8* WriteBoolNoTagToArray (bool value, output) INL; - static inline uint8* WriteEnumNoTagToArray (int value, output) INL; + INL static uint8* WriteInt32NoTagToArray (int32 value, output); + INL static uint8* WriteInt64NoTagToArray (int64 value, output); + INL static uint8* WriteUInt32NoTagToArray (uint32 value, output); + INL static uint8* WriteUInt64NoTagToArray (uint64 value, output); + INL static uint8* WriteSInt32NoTagToArray (int32 value, output); + INL static uint8* WriteSInt64NoTagToArray (int64 value, output); + INL static uint8* WriteFixed32NoTagToArray (uint32 value, output); + INL static uint8* WriteFixed64NoTagToArray (uint64 value, output); + INL static uint8* WriteSFixed32NoTagToArray(int32 value, output); + INL static uint8* WriteSFixed64NoTagToArray(int64 value, output); + INL static uint8* WriteFloatNoTagToArray (float value, output); + INL static uint8* WriteDoubleNoTagToArray (double value, output); + INL static uint8* WriteBoolNoTagToArray (bool value, output); + INL static uint8* WriteEnumNoTagToArray (int value, output); // Write fields, including tags. - static inline uint8* WriteInt32ToArray( - field_number, int32 value, output) INL; - static inline uint8* WriteInt64ToArray( - field_number, int64 value, output) INL; - static inline uint8* WriteUInt32ToArray( - field_number, uint32 value, output) INL; - static inline uint8* WriteUInt64ToArray( - field_number, uint64 value, output) INL; - static inline uint8* WriteSInt32ToArray( - field_number, int32 value, output) INL; - static inline uint8* WriteSInt64ToArray( - field_number, int64 value, output) INL; - static inline uint8* WriteFixed32ToArray( - field_number, uint32 value, output) INL; - static inline uint8* WriteFixed64ToArray( - field_number, uint64 value, output) INL; - static inline uint8* WriteSFixed32ToArray( - field_number, int32 value, output) INL; - static inline uint8* WriteSFixed64ToArray( - field_number, int64 value, output) INL; - static inline uint8* WriteFloatToArray( - field_number, float value, output) INL; - static inline uint8* WriteDoubleToArray( - field_number, double value, output) INL; - static inline uint8* WriteBoolToArray( - field_number, bool value, output) INL; - static inline uint8* WriteEnumToArray( - field_number, int value, output) INL; - - static inline uint8* WriteStringToArray( - field_number, const string& value, output) INL; - static inline uint8* WriteBytesToArray( - field_number, const string& value, output) INL; - - static inline uint8* WriteGroupToArray( - field_number, const MessageLite& value, output) INL; - static inline uint8* WriteMessageToArray( - field_number, const MessageLite& value, output) INL; + INL static uint8* WriteInt32ToArray(field_number, int32 value, output); + INL static uint8* WriteInt64ToArray(field_number, int64 value, output); + INL static uint8* WriteUInt32ToArray(field_number, uint32 value, output); + INL static uint8* WriteUInt64ToArray(field_number, uint64 value, output); + INL static uint8* WriteSInt32ToArray(field_number, int32 value, output); + INL static uint8* WriteSInt64ToArray(field_number, int64 value, output); + INL static uint8* WriteFixed32ToArray(field_number, uint32 value, output); + INL static uint8* WriteFixed64ToArray(field_number, uint64 value, output); + INL static uint8* WriteSFixed32ToArray(field_number, int32 value, output); + INL static uint8* WriteSFixed64ToArray(field_number, int64 value, output); + INL static uint8* WriteFloatToArray(field_number, float value, output); + INL static uint8* WriteDoubleToArray(field_number, double value, output); + INL static uint8* WriteBoolToArray(field_number, bool value, output); + INL static uint8* WriteEnumToArray(field_number, int value, output); + + INL static uint8* WriteStringToArray( + field_number, const string& value, output); + INL static uint8* WriteBytesToArray( + field_number, const string& value, output); + + INL static uint8* WriteGroupToArray( + field_number, const MessageLite& value, output); + INL static uint8* WriteMessageToArray( + field_number, const MessageLite& value, output); // Like above, but de-virtualize the call to SerializeWithCachedSizes(). The // pointer must point at an instance of MessageType, *not* a subclass (or // the subclass must not override SerializeWithCachedSizes()). template - static inline uint8* WriteGroupNoVirtualToArray( - field_number, const MessageType& value, output) INL; + INL static uint8* WriteGroupNoVirtualToArray( + field_number, const MessageType& value, output); template - static inline uint8* WriteMessageNoVirtualToArray( - field_number, const MessageType& value, output) INL; + INL static uint8* WriteMessageNoVirtualToArray( + field_number, const MessageType& value, output); #undef output #undef input @@ -527,18 +511,17 @@ class LIBPROTOBUF_EXPORT WireFormatLite { // A helper method for the repeated primitive reader. This method has // optimizations for primitive types that have fixed size on the wire, and // can be read using potentially faster paths. - template - static inline bool ReadRepeatedFixedSizePrimitive( + template GOOGLE_ATTRIBUTE_ALWAYS_INLINE + static bool ReadRepeatedFixedSizePrimitive( int tag_size, uint32 tag, google::protobuf::io::CodedInputStream* input, - RepeatedField* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + RepeatedField* value); // Like ReadRepeatedFixedSizePrimitive but for packed primitive fields. - template - static inline bool ReadPackedFixedSizePrimitive( - google::protobuf::io::CodedInputStream* input, - RepeatedField* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + template GOOGLE_ATTRIBUTE_ALWAYS_INLINE + static bool ReadPackedFixedSizePrimitive(google::protobuf::io::CodedInputStream* input, + RepeatedField* value); static const CppType kFieldTypeToCppTypeMap[]; static const WireFormatLite::WireType kWireTypeForFieldType[]; diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h index d073ff92..991c3d04 100644 --- a/src/google/protobuf/wire_format_lite_inl.h +++ b/src/google/protobuf/wire_format_lite_inl.h @@ -43,6 +43,7 @@ #include #include +#include #include #include #include diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc index aef22b29..15c37556 100644 --- a/src/google/protobuf/wire_format_unittest.cc +++ b/src/google/protobuf/wire_format_unittest.cc @@ -40,8 +40,10 @@ #include #include #include +#include #include +#include #include #include #include @@ -419,7 +421,7 @@ const int kUnknownTypeId = 1550055; TEST(WireFormatTest, SerializeMessageSet) { // Set up a TestMessageSet with two known messages and an unknown one. - unittest::TestMessageSet message_set; + proto2_wireformat_unittest::TestMessageSet message_set; message_set.MutableExtension( unittest::TestMessageSetExtension1::message_set_extension)->set_i(123); message_set.MutableExtension( @@ -462,7 +464,7 @@ TEST(WireFormatTest, SerializeMessageSetVariousWaysAreEqual) { // Set up a TestMessageSet with two known messages and an unknown one, as // above. - unittest::TestMessageSet message_set; + proto2_wireformat_unittest::TestMessageSet message_set; message_set.MutableExtension( unittest::TestMessageSetExtension1::message_set_extension)->set_i(123); message_set.MutableExtension( @@ -539,7 +541,7 @@ TEST(WireFormatTest, ParseMessageSet) { ASSERT_TRUE(raw.SerializeToString(&data)); // Parse as a TestMessageSet and check the contents. - unittest::TestMessageSet message_set; + proto2_wireformat_unittest::TestMessageSet message_set; ASSERT_TRUE(message_set.ParseFromString(data)); EXPECT_EQ(123, message_set.GetExtension( @@ -553,7 +555,7 @@ TEST(WireFormatTest, ParseMessageSet) { EXPECT_EQ("bar", message_set.unknown_fields().field(0).length_delimited()); // Also parse using WireFormat. - unittest::TestMessageSet dynamic_message_set; + proto2_wireformat_unittest::TestMessageSet dynamic_message_set; io::CodedInputStream input(reinterpret_cast(data.data()), data.size()); ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &dynamic_message_set)); @@ -583,7 +585,7 @@ TEST(WireFormatTest, ParseMessageSetWithReverseTagOrder) { coded_output.WriteTag(WireFormatLite::kMessageSetItemEndTag); } { - unittest::TestMessageSet message_set; + proto2_wireformat_unittest::TestMessageSet message_set; ASSERT_TRUE(message_set.ParseFromString(data)); EXPECT_EQ(123, message_set.GetExtension( @@ -591,7 +593,7 @@ TEST(WireFormatTest, ParseMessageSetWithReverseTagOrder) { } { // Test parse the message via Reflection. - unittest::TestMessageSet message_set; + proto2_wireformat_unittest::TestMessageSet message_set; io::CodedInputStream input( reinterpret_cast(data.data()), data.size()); EXPECT_TRUE(WireFormat::ParseAndMergePartial(&input, &message_set)); @@ -603,7 +605,7 @@ TEST(WireFormatTest, ParseMessageSetWithReverseTagOrder) { } TEST(WireFormatTest, ParseBrokenMessageSet) { - unittest::TestMessageSet message_set; + proto2_wireformat_unittest::TestMessageSet message_set; string input("goodbye"); // Invalid wire format data. EXPECT_FALSE(message_set.ParseFromString(input)); } -- cgit v1.2.3