aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/google/protobuf/any.cc17
-rw-r--r--src/google/protobuf/any.h1
-rwxr-xr-xsrc/google/protobuf/arena.cc15
-rw-r--r--src/google/protobuf/arena.h29
-rw-r--r--src/google/protobuf/arena_unittest.cc4
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc10
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc7
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.cc6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc2
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc1
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_doc_comment.cc98
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_doc_comment.h (renamed from src/google/protobuf/proto_cast_test.cc)43
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_enum.cc5
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_generator.cc21
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_helpers.cc35
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_helpers.h4
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_map_field.cc2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message.cc13
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message_field.cc3
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_names.h23
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_primitive_field.cc3
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc8
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc3
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field_lite.cc6
-rw-r--r--src/google/protobuf/compiler/java/java_map_field_lite.cc2
-rw-r--r--src/google/protobuf/compiler/java/java_message_lite.cc28
-rw-r--r--src/google/protobuf/compiler/main.cc2
-rw-r--r--src/google/protobuf/compiler/parser.cc25
-rw-r--r--src/google/protobuf/compiler/parser.h4
-rw-r--r--src/google/protobuf/compiler/parser_unittest.cc30
-rw-r--r--src/google/protobuf/compiler/python/python_generator.cc20
-rw-r--r--src/google/protobuf/descriptor.cc91
-rw-r--r--src/google/protobuf/descriptor.h39
-rw-r--r--src/google/protobuf/descriptor.pb.cc317
-rw-r--r--src/google/protobuf/descriptor.pb.h74
-rw-r--r--src/google/protobuf/descriptor.proto9
-rw-r--r--src/google/protobuf/descriptor_database_unittest.cc6
-rw-r--r--src/google/protobuf/descriptor_unittest.cc110
-rw-r--r--src/google/protobuf/dynamic_message.cc8
-rw-r--r--src/google/protobuf/dynamic_message_unittest.cc15
-rw-r--r--src/google/protobuf/extension_set.cc18
-rw-r--r--src/google/protobuf/extension_set.h15
-rw-r--r--src/google/protobuf/extension_set_unittest.cc5
-rw-r--r--src/google/protobuf/generated_message_reflection_unittest.cc11
-rw-r--r--src/google/protobuf/generated_message_util.cc2
-rw-r--r--src/google/protobuf/io/coded_stream_unittest.cc6
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl_lite.h8
-rw-r--r--src/google/protobuf/io/zero_copy_stream_unittest.cc6
-rw-r--r--src/google/protobuf/map.h10
-rw-r--r--src/google/protobuf/map_field_inl.h3
-rw-r--r--src/google/protobuf/map_proto2_unittest.proto6
-rw-r--r--src/google/protobuf/map_test.cc6
-rw-r--r--src/google/protobuf/map_type_handler.h24
-rw-r--r--src/google/protobuf/message.cc9
-rw-r--r--src/google/protobuf/message.h2
-rw-r--r--src/google/protobuf/metadata.h2
-rw-r--r--src/google/protobuf/proto_cast.h59
-rw-r--r--src/google/protobuf/repeated_field.h2
-rw-r--r--src/google/protobuf/stubs/callback.h4
-rw-r--r--src/google/protobuf/stubs/common.h2
-rw-r--r--src/google/protobuf/stubs/common_unittest.cc2
-rwxr-xr-xsrc/google/protobuf/stubs/hash.h13
-rw-r--r--src/google/protobuf/stubs/int128.cc3
-rw-r--r--src/google/protobuf/stubs/once_unittest.cc6
-rw-r--r--src/google/protobuf/stubs/stringpiece.h13
-rw-r--r--src/google/protobuf/stubs/stringpiece_unittest.cc18
-rw-r--r--src/google/protobuf/testing/googletest.cc7
-rw-r--r--src/google/protobuf/text_format.cc17
-rw-r--r--src/google/protobuf/text_format_unittest.cc10
-rw-r--r--src/google/protobuf/unittest_import.proto7
-rw-r--r--src/google/protobuf/unknown_enum_impl.h154
-rw-r--r--src/google/protobuf/unknown_enum_test.proto62
-rw-r--r--src/google/protobuf/util/field_comparator_test.cc2
-rw-r--r--src/google/protobuf/util/field_mask_util.cc10
-rw-r--r--src/google/protobuf/util/field_mask_util.h11
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter.h2
-rw-r--r--src/google/protobuf/util/internal/json_objectwriter.cc6
-rw-r--r--src/google/protobuf/util/internal/protostream_objectsource.cc22
-rw-r--r--src/google/protobuf/util/internal/protostream_objectsource.h4
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter.cc43
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter.h20
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter_test.cc144
-rw-r--r--src/google/protobuf/util/internal/utility.cc15
-rw-r--r--src/google/protobuf/util/internal/utility.h6
-rw-r--r--src/google/protobuf/util/json_format_proto3.proto10
-rw-r--r--src/google/protobuf/util/json_util.cc6
-rw-r--r--src/google/protobuf/util/json_util_test.cc2
-rw-r--r--src/google/protobuf/util/message_differencer.cc60
-rw-r--r--src/google/protobuf/util/message_differencer.h27
-rw-r--r--src/google/protobuf/util/time_util.h7
-rw-r--r--src/google/protobuf/util/type_resolver_util.cc71
95 files changed, 1415 insertions, 712 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index caae2933..2985b5d8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -434,6 +434,8 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/objectivec/objectivec_primitive_field.h \
google/protobuf/compiler/python/python_generator.cc \
google/protobuf/compiler/ruby/ruby_generator.cc \
+ google/protobuf/compiler/csharp/csharp_doc_comment.cc \
+ google/protobuf/compiler/csharp/csharp_doc_comment.h \
google/protobuf/compiler/csharp/csharp_enum.cc \
google/protobuf/compiler/csharp/csharp_enum.h \
google/protobuf/compiler/csharp/csharp_enum_field.cc \
diff --git a/src/google/protobuf/any.cc b/src/google/protobuf/any.cc
index c6ed37ae..7351d377 100644
--- a/src/google/protobuf/any.cc
+++ b/src/google/protobuf/any.cc
@@ -43,6 +43,7 @@ string GetTypeUrl(const Descriptor* message) {
const char kAnyFullTypeName[] = "google.protobuf.Any";
const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/";
+const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/";
AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value)
: type_url_(type_url), value_(value) {
@@ -70,11 +71,17 @@ bool AnyMetadata::InternalIs(const Descriptor* descriptor) const {
}
bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) {
- const int prefix_len = strlen(kTypeGoogleApisComPrefix);
- if (strncmp(type_url.c_str(), kTypeGoogleApisComPrefix, prefix_len) == 0) {
- full_type_name->assign(type_url.data() + prefix_len,
- type_url.size() - prefix_len);
- return true;
+ static const char* prefix[] = {
+ kTypeGoogleApisComPrefix,
+ kTypeGoogleProdComPrefix
+ };
+ for (int i = 0; i < 2; i++) {
+ const int prefix_len = strlen(prefix[i]);
+ if (strncmp(type_url.c_str(), prefix[i], prefix_len) == 0) {
+ full_type_name->assign(type_url.data() + prefix_len,
+ type_url.size() - prefix_len);
+ return true;
+ }
}
return false;
}
diff --git a/src/google/protobuf/any.h b/src/google/protobuf/any.h
index 7eeb6b70..f760ad5d 100644
--- a/src/google/protobuf/any.h
+++ b/src/google/protobuf/any.h
@@ -70,6 +70,7 @@ class LIBPROTOBUF_EXPORT AnyMetadata {
extern const char kAnyFullTypeName[]; // "google.protobuf.Any".
extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/".
+extern const char kTypeGoogleProdComPrefix[]; // "type.googleprod.com/".
// Get the proto type name from Any::type_url value. For example, passing
// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index 907a6a20..cd0b21a7 100755
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -38,17 +38,17 @@ namespace google {
namespace protobuf {
google::protobuf::internal::SequenceNumber Arena::lifecycle_id_generator_;
-#ifdef PROTOBUF_USE_DLLS
-Arena::ThreadCache& Arena::thread_cache() {
- static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL };
- return thread_cache_;
-}
-#elif defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
+#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
Arena::ThreadCache& Arena::thread_cache() {
static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ =
new internal::ThreadLocalStorage<ThreadCache>();
return *thread_cache_->Get();
}
+#elif defined(PROTOBUF_USE_DLLS)
+Arena::ThreadCache& Arena::thread_cache() {
+ static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL };
+ return thread_cache_;
+}
#else
GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL };
#endif
@@ -61,6 +61,9 @@ void Arena::Init() {
cleanup_list_ = 0;
if (options_.initial_block != NULL && options_.initial_block_size > 0) {
+ GOOGLE_CHECK_GE(options_.initial_block_size, sizeof(Block))
+ << ": Initial block size too small for header.";
+
// Add first unowned block to list.
Block* first_block = reinterpret_cast<Block*>(options_.initial_block);
first_block->size = options_.initial_block_size;
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index 074a9e54..16e0d50e 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -38,7 +38,16 @@
#if __cplusplus >= 201103L
#include <google/protobuf/stubs/type_traits.h>
#endif
+#if defined(_MSC_VER) && !_HAS_EXCEPTIONS
+// Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0.
+#include <exception>
#include <typeinfo>
+namespace std {
+using type_info = ::type_info;
+}
+#else
+#include <typeinfo>
+#endif
#include <google/protobuf/stubs/atomic_sequence_num.h>
#include <google/protobuf/stubs/atomicops.h>
@@ -533,15 +542,15 @@ class LIBPROTOBUF_EXPORT Arena {
static const size_t kHeaderSize = sizeof(Block);
static google::protobuf::internal::SequenceNumber lifecycle_id_generator_;
-#ifdef PROTOBUF_USE_DLLS
- // Thread local variables cannot be exposed through DLL interface but we can
- // wrap them in static functions.
- static ThreadCache& thread_cache();
-#elif defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
+#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
// Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread
// local storage class we implemented.
// iOS also does not support the GOOGLE_THREAD_LOCAL keyword.
static ThreadCache& thread_cache();
+#elif defined(PROTOBUF_USE_DLLS)
+ // Thread local variables cannot be exposed through DLL interface but we can
+ // wrap them in static functions.
+ static ThreadCache& thread_cache();
#else
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
static ThreadCache& thread_cache() { return thread_cache_; }
@@ -581,11 +590,13 @@ class LIBPROTOBUF_EXPORT Arena {
template<typename U>
static double DestructorSkippable(...);
+ // The raw_skippable_value const bool variable is separated from the typedef
+ // line below as a work-around of an NVCC 7.0 (and earlier) compiler bug.
+ static const bool raw_skippable_value =
+ sizeof(DestructorSkippable<const T>(static_cast<const T*>(0))) ==
+ sizeof(char) || google::protobuf::internal::has_trivial_destructor<T>::value == true;
// This will resolve to either google::protobuf::internal::true_type or google::protobuf::internal::false_type.
- typedef google::protobuf::internal::integral_constant<bool,
- sizeof(DestructorSkippable<const T>(static_cast<const T*>(0))) ==
- sizeof(char) || google::protobuf::internal::has_trivial_destructor<T>::value == true>
- type;
+ typedef google::protobuf::internal::integral_constant<bool, raw_skippable_value> type;
static const type value;
};
diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc
index c9ca1fd1..6b67f446 100644
--- a/src/google/protobuf/arena_unittest.cc
+++ b/src/google/protobuf/arena_unittest.cc
@@ -362,7 +362,7 @@ TEST(ArenaTest, ReleaseMessage) {
Arena arena;
TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
arena_message->mutable_optional_nested_message()->set_bb(118);
- scoped_ptr<TestAllTypes::NestedMessage> nested(
+ google::protobuf::scoped_ptr<TestAllTypes::NestedMessage> nested(
arena_message->release_optional_nested_message());
EXPECT_EQ(118, nested->bb());
@@ -383,7 +383,7 @@ TEST(ArenaTest, ReleaseString) {
Arena arena;
TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
arena_message->set_optional_string("hello");
- scoped_ptr<string> released_str(
+ google::protobuf::scoped_ptr<string> released_str(
arena_message->release_optional_string());
EXPECT_EQ("hello", *released_str);
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index 18102f4d..fa792dae 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -63,13 +63,13 @@
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
-namespace google {
-namespace protobuf {
-namespace compiler {
// Disable the whole test when we use tcmalloc for "draconian" heap checks, in
// which case tcmalloc will print warnings that fail the plugin tests.
#if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
+namespace google {
+namespace protobuf {
+namespace compiler {
#if defined(_WIN32)
#ifndef STDIN_FILENO
@@ -1802,8 +1802,8 @@ TEST_F(EncodeDecodeTest, ProtoParseError) {
} // anonymous namespace
-#endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
-
} // namespace compiler
} // namespace protobuf
+
+#endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
} // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index 5dae4cdd..8e8bd8b7 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -598,8 +598,13 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// bytes in length". Declare a static array of characters rather than use a
// string literal.
if (breakdown_large_file && file_data.size() > 65535) {
+ // This has to be explicitly marked as a signed char because the generated
+ // code puts negative values in the array, and sometimes plain char is
+ // unsigned. That implicit narrowing conversion is not allowed in C++11.
+ // <http://stackoverflow.com/questions/4434140/narrowing-conversions-in-c0x-is-it-just-me-or-does-this-sound-like-a-breakin>
+ // has details on why.
printer->Print(
- "static const char descriptor[] = {\n");
+ "static const signed char descriptor[] = {\n");
printer->Indent();
// Only write 25 bytes per line.
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index 25acc61b..e5e2f07d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -66,7 +66,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
(*variables)["wrapper"] = "EntryWrapper";
break;
case FieldDescriptor::CPPTYPE_ENUM:
- (*variables)["val_cpp"] = ClassName(val->enum_type(), false);
+ (*variables)["val_cpp"] = ClassName(val->enum_type(), true);
(*variables)["wrapper"] = "EnumEntryWrapper";
break;
default:
@@ -200,7 +200,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
case FieldDescriptor::CPPTYPE_ENUM:
printer->Print(variables_,
"(*mutable_$name$())[entry->key()] =\n"
- " static_cast<$val_cpp$>(*entry->mutable_value());\n");
+ " static_cast< $val_cpp$ >(*entry->mutable_value());\n");
break;
default:
printer->Print(variables_,
@@ -215,7 +215,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
" DO_(entry->ParseFromString(data));\n"
" if ($val_cpp$_IsValid(*entry->mutable_value())) {\n"
" (*mutable_$name$())[entry->key()] =\n"
- " static_cast<$val_cpp$>(*entry->mutable_value());\n"
+ " static_cast< $val_cpp$ >(*entry->mutable_value());\n"
" } else {\n");
if (HasDescriptorMethods(descriptor_->file())) {
printer->Print(variables_,
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index fc1ce962..8cc8c7ba 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -350,7 +350,7 @@ void CollectMapInfo(const Descriptor* descriptor,
(*variables)["val"] = FieldMessageTypeName(val);
break;
case FieldDescriptor::CPPTYPE_ENUM:
- (*variables)["val"] = ClassName(val->enum_type(), false);
+ (*variables)["val"] = ClassName(val->enum_type(), true);
break;
default:
(*variables)["val"] = PrimitiveTypeName(val->cpp_type());
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index b7b6039a..9942a343 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -82,6 +82,7 @@
namespace google {
namespace protobuf {
+using internal::NewPermanentCallback;
namespace compiler {
namespace cpp {
diff --git a/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc b/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
new file mode 100644
index 00000000..9ad2cbb5
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
@@ -0,0 +1,98 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+// Functions to create C# XML documentation comments.
+// Currently this only includes documentation comments containing text specified as comments
+// in the .proto file; documentation comments generated just from field/message/enum/proto names
+// is inlined in the relevant code. If more control is required, that code can be moved here.
+
+void WriteDocCommentBodyImpl(io::Printer* printer, SourceLocation location) {
+ string comments = location.leading_comments.empty() ?
+ location.trailing_comments : location.leading_comments;
+ if (comments.empty()) {
+ return;
+ }
+ // XML escaping... no need for apostrophes etc as the whole text is going to be a child
+ // node of a summary element, not part of an attribute.
+ comments = StringReplace(comments, "&", "&amp;", true);
+ comments = StringReplace(comments, "<", "&lt;", true);
+ vector<string> lines = Split(comments, "\n");
+ printer->Print("/// <summary>\n");
+ for (std::vector<string>::iterator it = lines.begin(); it != lines.end(); ++it) {
+ printer->Print("/// $line$\n", "line", *it);
+ }
+ printer->Print("/// </summary>\n");
+}
+
+template <typename DescriptorType>
+static void WriteDocCommentBody(
+ io::Printer* printer, const DescriptorType* descriptor) {
+ SourceLocation location;
+ if (descriptor->GetSourceLocation(&location)) {
+ WriteDocCommentBodyImpl(printer, location);
+ }
+}
+
+void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) {
+ WriteDocCommentBody(printer, message);
+}
+
+void WritePropertyDocComment(io::Printer* printer, const FieldDescriptor* field) {
+ WriteDocCommentBody(printer, field);
+}
+
+void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enumDescriptor) {
+ WriteDocCommentBody(printer, enumDescriptor);
+}
+void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value) {
+ WriteDocCommentBody(printer, value);
+}
+
+void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method) {
+ WriteDocCommentBody(printer, method);
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/proto_cast_test.cc b/src/google/protobuf/compiler/csharp/csharp_doc_comment.h
index a8f43ae4..75eb0ea0 100644
--- a/src/google/protobuf/proto_cast_test.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_doc_comment.h
@@ -28,33 +28,24 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include <google/protobuf/util/proto_cast.h>
-#include <google/protobuf/util/unknown_enum_test.pb.h>
-#include <gtest/gtest.h>
-#include <gmock/gmock.h>
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
-namespace google {
-using google::protobuf::util::UpRevision;
-using google::protobuf::util::DownRevision;
-
-namespace {
-
-TEST(ProtoCastTest, V2KnownValue) {
- UpRevision sender;
- sender.set_value(UpRevision::NONDEFAULT_VALUE);
-
- DownRevision receiver = proto_cast<DownRevision>(sender);
- ASSERT_EQ(DownRevision::NONDEFAULT_VALUE, receiver.value());
-}
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.h>
-TEST(ProtoCastTest, V2UnknownValue) {
- UpRevision sender;
- sender.set_value(UpRevision::NEW_VALUE);
-
- DownRevision receiver = proto_cast<DownRevision>(sender);
- ASSERT_EQ(DownRevision::DEFAULT_VALUE, receiver.value());
-}
-
-} // namespace
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+ void WriteMessageDocComment(io::Printer* printer, const Descriptor* message);
+ void WritePropertyDocComment(io::Printer* printer, const FieldDescriptor* field);
+ void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enumDescriptor);
+ void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value);
+ void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method);
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc
index 0e8f9836..56681989 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_enum.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
@@ -57,13 +58,15 @@ EnumGenerator::~EnumGenerator() {
}
void EnumGenerator::Generate(io::Printer* printer) {
+ WriteEnumDocComment(printer, descriptor_);
WriteGeneratedCodeAttributes(printer);
printer->Print("$access_level$ enum $name$ {\n",
"access_level", class_access_level(),
"name", descriptor_->name());
printer->Indent();
for (int i = 0; i < descriptor_->value_count(); i++) {
- printer->Print("$name$ = $number$,\n",
+ WriteEnumValueDocComment(printer, descriptor_->value(i));
+ printer->Print("$name$ = $number$,\n",
"name", descriptor_->value(i)->name(),
"number", SimpleItoa(descriptor_->value(i)->number()));
}
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc
index e0a6c83a..f5ff880f 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc
@@ -36,10 +36,12 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/compiler/csharp/csharp_generator.h>
-#include <google/protobuf/compiler/csharp/csharp_umbrella_class.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_names.h>
+#include <google/protobuf/compiler/csharp/csharp_umbrella_class.h>
using google::protobuf::internal::scoped_ptr;
@@ -48,11 +50,6 @@ namespace protobuf {
namespace compiler {
namespace csharp {
-std::string GetOutputFile(const google::protobuf::FileDescriptor* file, const std::string file_extension)
-{
- return GetUmbrellaClassUnqualifiedName(file) + file_extension;
-}
-
void GenerateFile(const google::protobuf::FileDescriptor* file,
io::Printer* printer) {
UmbrellaClassGenerator umbrellaGenerator(file);
@@ -75,16 +72,26 @@ bool Generator::Generate(
}
std::string file_extension = ".cs";
+ std::string base_namespace = "";
+ bool generate_directories = false;
for (int i = 0; i < options.size(); i++) {
if (options[i].first == "file_extension") {
file_extension = options[i].second;
+ } else if (options[i].first == "base_namespace") {
+ base_namespace = options[i].second;
+ generate_directories = true;
} else {
*error = "Unknown generator option: " + options[i].first;
return false;
}
}
- std::string filename = GetOutputFile(file, file_extension);
+ string filename_error = "";
+ std::string filename = GetOutputFile(file, file_extension, generate_directories, base_namespace, &filename_error);
+ if (filename.empty()) {
+ *error = filename_error;
+ return false;
+ }
scoped_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(filename));
io::Printer printer(output.get(), '$');
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
index 333b4912..2264b88d 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
@@ -269,6 +269,41 @@ std::string GetPropertyName(const FieldDescriptor* descriptor) {
return property_name;
}
+std::string GetOutputFile(
+ const google::protobuf::FileDescriptor* descriptor,
+ const std::string file_extension,
+ const bool generate_directories,
+ const std::string base_namespace,
+ string* error) {
+ string relative_filename = GetUmbrellaClassUnqualifiedName(descriptor) + file_extension;
+ if (!generate_directories) {
+ return relative_filename;
+ }
+ string ns = GetFileNamespace(descriptor);
+ string namespace_suffix = ns;
+ if (!base_namespace.empty()) {
+ // Check that the base_namespace is either equal to or a leading part of
+ // the file namespace. This isn't just a simple prefix; "Foo.B" shouldn't
+ // be regarded as a prefix of "Foo.Bar". The simplest option is to add "."
+ // to both.
+ string extended_ns = ns + ".";
+ if (extended_ns.find(base_namespace + ".") != 0) {
+ *error = "Namespace " + ns + " is not a prefix namespace of base namespace " + base_namespace;
+ return ""; // This will be ignored, because we've set an error.
+ }
+ namespace_suffix = ns.substr(base_namespace.length());
+ if (namespace_suffix.find(".") == 0) {
+ namespace_suffix = namespace_suffix.substr(1);
+ }
+ }
+
+ string namespace_dir = StringReplace(namespace_suffix, ".", "/", true);
+ if (!namespace_dir.empty()) {
+ namespace_dir += "/";
+ }
+ return namespace_dir + relative_filename;
+}
+
// TODO: c&p from Java protoc plugin
// For encodings with fixed sizes, returns that size in bytes. Otherwise
// returns -1.
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h
index 4ed17a84..4f393e1c 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.h
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h
@@ -76,8 +76,6 @@ std::string GetUmbrellaClassUnqualifiedName(const FileDescriptor* descriptor);
// not including the GetFileNamespace part).
std::string GetUmbrellaClassNestedNamespace(const FileDescriptor* descriptor);
-std::string GetClassName(const Descriptor* descriptor);
-
std::string GetClassName(const EnumDescriptor* descriptor);
std::string GetFieldName(const FieldDescriptor* descriptor);
@@ -101,8 +99,6 @@ std::string StringToBase64(const std::string& input);
std::string FileDescriptorToBase64(const FileDescriptor* descriptor);
-uint FixedMakeTag(const FieldDescriptor* descriptor);
-
FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
// Determines whether the given message is a map entry message, i.e. one implicitly created
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
index f84ad6f7..b493495d 100644
--- a/src/google/protobuf/compiler/csharp/csharp_map_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_map_field.h>
@@ -76,6 +77,7 @@ void MapFieldGenerator::GenerateMembers(io::Printer* printer) {
variables_,
", $tag$);\n"
"private readonly pbc::MapField<$key_type_name$, $value_type_name$> $name$_ = new pbc::MapField<$key_type_name$, $value_type_name$>($true_for_wrappers$);\n");
+ WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc
index a71a7909..21fbf7e3 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message.cc
@@ -42,6 +42,7 @@
#include <google/protobuf/wire_format.h>
#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_enum.h>
#include <google/protobuf/compiler/csharp/csharp_field_base.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
@@ -101,6 +102,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
vars["class_name"] = class_name();
vars["access_level"] = class_access_level();
+ WriteMessageDocComment(printer, descriptor_);
printer->Print(
"[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
WriteGeneratedCodeAttributes(printer);
@@ -152,7 +154,9 @@ void MessageGenerator::Generate(io::Printer* printer) {
// Rats: we lose the debug comment here :(
printer->Print(
+ "/// <summary>Field number for the \"$field_name$\" field.</summary>\n"
"public const int $field_constant_name$ = $index$;\n",
+ "field_name", fieldDescriptor->name(),
"field_constant_name", GetFieldConstantName(fieldDescriptor),
"index", SimpleItoa(fieldDescriptor->number()));
scoped_ptr<FieldGeneratorBase> generator(
@@ -169,6 +173,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
printer->Print(
vars,
"private object $name$_;\n"
+ "/// <summary>Enum of possible cases for the \"$original_name$\" oneof.</summary>\n"
"public enum $property_name$OneofCase {\n");
printer->Indent();
printer->Print("None = 0,\n");
@@ -180,6 +185,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
}
printer->Outdent();
printer->Print("}\n");
+ // TODO: Should we put the oneof .proto comments here? It's unclear exactly where they should go.
printer->Print(
vars,
"private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n"
@@ -199,8 +205,11 @@ void MessageGenerator::Generate(io::Printer* printer) {
// Nested messages and enums
if (HasNestedGeneratedTypes()) {
- printer->Print("#region Nested types\n"
- "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
+ printer->Print(
+ vars,
+ "#region Nested types\n"
+ "/// <summary>Container for nested types declared in the $class_name$ message type.</summary>\n"
+ "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
WriteGeneratedCodeAttributes(printer);
printer->Print("public static partial class Types {\n");
printer->Indent();
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
index 4f576cd1..f81f769b 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_message_field.h>
@@ -61,6 +62,7 @@ void MessageFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
variables_,
"private $type_name$ $name$_;\n");
+ WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
@@ -152,6 +154,7 @@ MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {
}
void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
+ WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
diff --git a/src/google/protobuf/compiler/csharp/csharp_names.h b/src/google/protobuf/compiler/csharp/csharp_names.h
index ccd2e720..23dac1c7 100644
--- a/src/google/protobuf/compiler/csharp/csharp_names.h
+++ b/src/google/protobuf/compiler/csharp/csharp_names.h
@@ -72,7 +72,28 @@ string GetClassName(const Descriptor* descriptor);
// The fully-qualified name of the C# class that provides
// access to the file descriptor. Proto compiler generates
// such class for each .proto file processed.
-std::string GetUmbrellaClassName(const FileDescriptor* descriptor);
+string GetUmbrellaClassName(const FileDescriptor* descriptor);
+
+// Generates output file name for given file descriptor. If generate_directories
+// is true, the output file will be put under directory corresponding to file's
+// namespace. base_namespace can be used to strip some of the top level
+// directories. E.g. for file with namespace "Bar.Foo" and base_namespace="Bar",
+// the resulting file will be put under directory "Foo" (and not "Bar/Foo").
+//
+// Requires:
+// descriptor != NULL
+// error != NULL
+//
+// Returns:
+// The file name to use as output file for given file descriptor. In case
+// of failure, this function will return empty string and error parameter
+// will contain the error message.
+string GetOutputFile(
+ const google::protobuf::FileDescriptor* descriptor,
+ const string file_extension,
+ const bool generate_directories,
+ const string base_namespace,
+ string* error);
} // namespace csharp
} // namespace compiler
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
index fc043ec0..76d5b247 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
@@ -68,6 +69,7 @@ void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
variables_,
"private $type_name$ $name_def_message$;\n");
+ WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
@@ -170,6 +172,7 @@ PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {
}
void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
+ WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
index 625631df..3a11b75d 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/wire_format.h>
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
@@ -62,6 +63,7 @@ void RepeatedEnumFieldGenerator::GenerateMembers(io::Printer* printer) {
" = pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x);\n");
printer->Print(variables_,
"private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
+ WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
index 7fbab681..fc12faed 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
@@ -37,6 +37,7 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h>
#include <google/protobuf/compiler/csharp/csharp_message_field.h>
@@ -75,6 +76,7 @@ void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
variables_,
"private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
+ WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
index 1163ce73..5fe0b203 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/wire_format.h>
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h>
@@ -62,6 +63,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
" = pb::FieldCodec.For$capitalized_type_name$($tag$);\n");
printer->Print(variables_,
"private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
+ WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
index 399c64e1..7cf101b0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
@@ -135,7 +135,9 @@ void UmbrellaClassGenerator::WriteIntroduction(io::Printer* printer) {
}
printer->Print(
- "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
+ "/// <summary>Holder for reflection information generated from $file_name$</summary>\n"
+ "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n",
+ "file_name", file_->name());
WriteGeneratedCodeAttributes(printer);
printer->Print(
"$access_level$ static partial class $umbrella_class_name$ {\n"
@@ -148,12 +150,14 @@ void UmbrellaClassGenerator::WriteIntroduction(io::Printer* printer) {
void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) {
printer->Print(
"#region Descriptor\n"
+ "/// <summary>File descriptor for $file_name$</summary>\n"
"public static pbr::FileDescriptor Descriptor {\n"
" get { return descriptor; }\n"
"}\n"
"private static pbr::FileDescriptor descriptor;\n"
"\n"
"static $umbrella_class_name$() {\n",
+ "file_name", file_->name(),
"umbrella_class_name", umbrellaClassname_);
printer->Indent();
printer->Print(
@@ -166,7 +170,7 @@ void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) {
// TODO(jonskeet): Consider a C#-escaping format here instead of just Base64.
std::string base64 = FileDescriptorToBase64(file_);
while (base64.size() > 60) {
- printer->Print("\"$base64$\", \n", "base64", base64.substr(0, 60));
+ printer->Print("\"$base64$\",\n", "base64", base64.substr(0, 60));
base64 = base64.substr(60);
}
printer->Print("\"$base64$\"));\n", "base64", base64);
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
index 44f832bf..6a3750e0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
@@ -37,6 +37,7 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
@@ -70,6 +71,7 @@ void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) {
variables_,
";\n"
"private $type_name$ $name$_;\n");
+ WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
@@ -165,6 +167,7 @@ void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
"private static readonly pb::FieldCodec<$type_name$> _oneof_$name$_codec = ");
GenerateCodecCode(printer);
printer->Print(";\n");
+ WritePropertyDocComment(printer, descriptor_);
AddDeprecatedFlag(printer);
printer->Print(
variables_,
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
index 2c3608c2..e8bf15d0 100644
--- a/src/google/protobuf/compiler/java/java_enum_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
@@ -299,7 +299,7 @@ GenerateParsingCode(io::Printer* printer) const {
"if (value == null) {\n");
if (PreserveUnknownFields(descriptor_->containing_type())) {
printer->Print(variables_,
- " unknownFields.mergeVarintField($number$, rawValue);\n");
+ " super.mergeVarintField($number$, rawValue);\n");
}
printer->Print(variables_,
"} else {\n"
@@ -492,7 +492,7 @@ GenerateParsingCode(io::Printer* printer) const {
"if (value == null) {\n");
if (PreserveUnknownFields(descriptor_->containing_type())) {
printer->Print(variables_,
- " unknownFields.mergeVarintField($number$, rawValue);\n");
+ " super.mergeVarintField($number$, rawValue);\n");
}
printer->Print(variables_,
"} else {\n"
@@ -850,7 +850,7 @@ GenerateParsingCode(io::Printer* printer) const {
"if (value == null) {\n");
if (PreserveUnknownFields(descriptor_->containing_type())) {
printer->Print(variables_,
- " unknownFields.mergeVarintField($number$, rawValue);\n");
+ " super.mergeVarintField($number$, rawValue);\n");
}
printer->Print(variables_,
"} else {\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 4fe656d3..d2039403 100644
--- a/src/google/protobuf/compiler/java/java_map_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc
@@ -405,7 +405,7 @@ GenerateParsingCode(io::Printer* printer) const {
printer->Print(
variables_,
"if ($value_enum_type$.valueOf($name$.getValue()) == null) {\n"
- " unknownFields.mergeLengthDelimitedField($number$, bytes);\n"
+ " super.mergeLengthDelimitedField($number$, bytes);\n"
"} else {\n"
" $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
"}\n");
diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc
index 8b6c75b8..94ed2c39 100644
--- a/src/google/protobuf/compiler/java/java_message_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -1029,12 +1029,6 @@ GenerateParsingConstructor(io::Printer* printer) {
"bit_field_name", GetBitFieldName(i));
}
- if (PreserveUnknownFields(descriptor_)) {
- printer->Print(
- "com.google.protobuf.UnknownFieldSetLite.Builder unknownFields =\n"
- " com.google.protobuf.UnknownFieldSetLite.newBuilder();\n");
- }
-
printer->Print(
"try {\n");
printer->Indent();
@@ -1056,13 +1050,10 @@ GenerateParsingConstructor(io::Printer* printer) {
if (PreserveUnknownFields(descriptor_)) {
if (descriptor_->extension_range_count() > 0) {
- // Lite runtime directly invokes parseUnknownField to reduce method
- // counts.
printer->Print(
"default: {\n"
- " if (!parseUnknownField(extensions, getDefaultInstanceForType(),\n"
- " input, unknownFields,\n"
- " extensionRegistry, tag)) {\n"
+ " if (!parseUnknownField(getDefaultInstanceForType(),\n"
+ " input, extensionRegistry, tag)) {\n"
" done = true;\n" // it's an endgroup tag
" }\n"
" break;\n"
@@ -1070,8 +1061,7 @@ GenerateParsingConstructor(io::Printer* printer) {
} else {
printer->Print(
"default: {\n"
- " if (!parseUnknownField(input, unknownFields,\n"
- " extensionRegistry, tag)) {\n"
+ " if (!parseUnknownField(tag, input)) {\n"
" done = true;\n" // it's an endgroup tag
" }\n"
" break;\n"
@@ -1146,16 +1136,8 @@ GenerateParsingConstructor(io::Printer* printer) {
field_generators_.get(field).GenerateParsingDoneCode(printer);
}
- if (PreserveUnknownFields(descriptor_)) {
- // Make unknown fields immutable.
- printer->Print("this.unknownFields = unknownFields.build();\n");
- }
-
- if (descriptor_->extension_range_count() > 0) {
- // Make extensions immutable.
- printer->Print(
- "makeExtensionsImmutable(extensions);\n");
- }
+ printer->Print(
+ "doneParsing();\n");
printer->Outdent();
printer->Outdent();
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
index 4815a726..584e5a40 100644
--- a/src/google/protobuf/compiler/main.cc
+++ b/src/google/protobuf/compiler/main.cc
@@ -72,7 +72,7 @@ int main(int argc, char* argv[]) {
// CSharp
google::protobuf::compiler::csharp::Generator csharp_generator;
- cli.RegisterGenerator("--csharp_out", &csharp_generator,
+ cli.RegisterGenerator("--csharp_out", "--csharp_opt", &csharp_generator,
"Generate C# source file.");
// Objective C
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index 4d018425..a389a4fc 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -993,6 +993,9 @@ bool Parser::ParseFieldOptions(FieldDescriptorProto* field,
// We intentionally pass field_location rather than location here, since
// the default value is not actually an option.
DO(ParseDefaultAssignment(field, field_location, containing_file));
+ } else if (LookingAt("json_name")) {
+ // Like default value, this "json_name" is not an actual option.
+ DO(ParseJsonName(field, field_location, containing_file));
} else {
DO(ParseOption(field->mutable_options(), location,
containing_file, OPTION_ASSIGNMENT));
@@ -1140,6 +1143,28 @@ bool Parser::ParseDefaultAssignment(
return true;
}
+bool Parser::ParseJsonName(
+ FieldDescriptorProto* field,
+ const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file) {
+ if (field->has_json_name()) {
+ AddError("Already set option \"json_name\".");
+ field->clear_json_name();
+ }
+
+ DO(Consume("json_name"));
+ DO(Consume("="));
+
+ LocationRecorder location(field_location,
+ FieldDescriptorProto::kJsonNameFieldNumber);
+ location.RecordLegacyLocation(
+ field, DescriptorPool::ErrorCollector::OPTION_VALUE);
+ DO(ConsumeString(field->mutable_json_name(),
+ "Expected string for JSON name."));
+ return true;
+}
+
+
bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
const LocationRecorder& part_location,
const FileDescriptorProto* containing_file) {
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index 007b001c..3ba1e170 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -439,6 +439,10 @@ class LIBPROTOBUF_EXPORT Parser {
const LocationRecorder& field_location,
const FileDescriptorProto* containing_file);
+ bool ParseJsonName(FieldDescriptorProto* field,
+ const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file);
+
enum OptionStyle {
OPTION_ASSIGNMENT, // just "name = value"
OPTION_STATEMENT // "option name = value;"
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index cc6f1efb..0d729e0b 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -452,6 +452,20 @@ TEST_F(ParseMessageTest, FieldDefaults) {
#undef ETC
}
+TEST_F(ParseMessageTest, FieldJsonName) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " optional string foo = 1 [json_name = \"@type\"];\n"
+ "}\n",
+ "message_type {"
+ " name: \"TestMessage\""
+ " field {\n"
+ " name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: 1"
+ " json_name: \"@type\"\n"
+ " }\n"
+ "}\n");
+}
+
TEST_F(ParseMessageTest, FieldOptions) {
ExpectParsesTo(
"message TestMessage {\n"
@@ -1126,6 +1140,22 @@ TEST_F(ParseErrorTest, DefaultValueTooLarge) {
"6:36: Integer out of range.\n");
}
+TEST_F(ParseErrorTest, JsonNameNotString) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional string foo = 1 [json_name=1];\n"
+ "}\n",
+ "1:37: Expected string for JSON name.\n");
+}
+
+TEST_F(ParseErrorTest, DuplicateJsonName) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional uint32 foo = 1 [json_name=\"a\",json_name=\"b\"];\n"
+ "}\n",
+ "1:41: Already set option \"json_name\".\n");
+}
+
TEST_F(ParseErrorTest, EnumValueOutOfRange) {
ExpectHasErrors(
"enum TestEnum {\n"
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index e81af700..4d500f90 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.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.
+//#PY25 compatible generated code for GAE.
// Copyright 2007 Google Inc. All Rights Reserved.
// Author: robinson@google.com (Will Robinson)
//
@@ -166,6 +167,7 @@ void PrintTopBoilerplate(
printer->Print(
"# Generated by the protocol buffer compiler. DO NOT EDIT!\n"
"# source: $filename$\n"
+ "\nimport sys\n_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))" //##PY25
"\n",
"filename", file->name());
if (HasTopLevelEnums(file)) {
@@ -257,9 +259,12 @@ string StringifyDefaultValue(const FieldDescriptor& field) {
case FieldDescriptor::CPPTYPE_ENUM:
return SimpleItoa(field.default_value_enum()->number());
case FieldDescriptor::CPPTYPE_STRING:
- return "b\"" + CEscape(field.default_value_string()) +
- (field.type() != FieldDescriptor::TYPE_STRING ? "\"" :
- "\".decode('utf-8')");
+//##!PY25 return "b\"" + CEscape(field.default_value_string()) +
+//##!PY25 (field.type() != FieldDescriptor::TYPE_STRING ? "\"" :
+//##!PY25 "\".decode('utf-8')");
+ return "_b(\"" + CEscape(field.default_value_string()) + //##PY25
+ (field.type() != FieldDescriptor::TYPE_STRING ? "\")" : //##PY25
+ "\").decode('utf-8')"); //##PY25
case FieldDescriptor::CPPTYPE_MESSAGE:
return "None";
}
@@ -385,7 +390,8 @@ void Generator::PrintFileDescriptor() const {
printer_->Print(m, file_descriptor_template);
printer_->Indent();
printer_->Print(
- "serialized_pb=b'$value$'\n",
+//##!PY25 "serialized_pb=b'$value$'\n",
+ "serialized_pb=_b('$value$')\n", //##PY25
"value", strings::CHexEscape(file_descriptor_serialized_));
if (file_->dependency_count() != 0) {
printer_->Print(",\ndependencies=[");
@@ -1029,8 +1035,10 @@ string Generator::OptionsValue(
return "None";
} else {
string full_class_name = "descriptor_pb2." + class_name;
- return "_descriptor._ParseOptions(" + full_class_name + "(), b'"
- + CEscape(serialized_options)+ "')";
+//##!PY25 return "_descriptor._ParseOptions(" + full_class_name + "(), b'"
+//##!PY25 + CEscape(serialized_options)+ "')";
+ return "_descriptor._ParseOptions(" + full_class_name + "(), _b('" //##PY25
+ + CEscape(serialized_options)+ "'))"; //##PY25
}
}
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 5256b83c..b40fe95a 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -34,6 +34,10 @@
#include <google/protobuf/stubs/hash.h>
#include <map>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <set>
#include <string>
#include <vector>
@@ -1726,6 +1730,20 @@ void FileDescriptor::CopyTo(FileDescriptorProto* proto) const {
}
}
+void FileDescriptor::CopyJsonNameTo(FileDescriptorProto* proto) const {
+ if (message_type_count() != proto->message_type_size() ||
+ extension_count() != proto->extension_size()) {
+ GOOGLE_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
+ return;
+ }
+ for (int i = 0; i < message_type_count(); i++) {
+ message_type(i)->CopyJsonNameTo(proto->mutable_message_type(i));
+ }
+ for (int i = 0; i < extension_count(); i++) {
+ extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
+ }
+}
+
void FileDescriptor::CopySourceCodeInfoTo(FileDescriptorProto* proto) const {
if (source_code_info_ &&
source_code_info_ != &SourceCodeInfo::default_instance()) {
@@ -1770,9 +1788,30 @@ void Descriptor::CopyTo(DescriptorProto* proto) const {
}
}
+void Descriptor::CopyJsonNameTo(DescriptorProto* proto) const {
+ if (field_count() != proto->field_size() ||
+ nested_type_count() != proto->nested_type_size() ||
+ extension_count() != proto->extension_size()) {
+ GOOGLE_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
+ return;
+ }
+ for (int i = 0; i < field_count(); i++) {
+ field(i)->CopyJsonNameTo(proto->mutable_field(i));
+ }
+ for (int i = 0; i < nested_type_count(); i++) {
+ nested_type(i)->CopyJsonNameTo(proto->mutable_nested_type(i));
+ }
+ for (int i = 0; i < extension_count(); i++) {
+ extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
+ }
+}
+
void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const {
proto->set_name(name());
proto->set_number(number());
+ if (has_json_name_) {
+ proto->set_json_name(json_name());
+ }
// Some compilers do not allow static_cast directly between two enum types,
// so we must cast to int first.
@@ -1819,6 +1858,10 @@ void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const {
}
}
+void FieldDescriptor::CopyJsonNameTo(FieldDescriptorProto* proto) const {
+ proto->set_json_name(json_name());
+}
+
void OneofDescriptor::CopyTo(OneofDescriptorProto* proto) const {
proto->set_name(name());
}
@@ -4136,6 +4179,14 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
tables_->AllocateString(ToCamelCase(proto.name(),
/* lower_first = */ true));
+ if (proto.has_json_name()) {
+ result->has_json_name_ = true;
+ result->json_name_ = tables_->AllocateString(proto.json_name());
+ } else {
+ result->has_json_name_ = false;
+ result->json_name_ = result->camelcase_name_;
+ }
+
// Some compilers do not allow static_cast directly between two enum types,
// so we must cast to int first.
result->type_ = static_cast<FieldDescriptor::Type>(
@@ -5040,6 +5091,20 @@ void DescriptorBuilder::ValidateProto3(
}
}
+static string ToLowercaseWithoutUnderscores(const string& name) {
+ string result;
+ for (int i = 0; i < name.size(); ++i) {
+ if (name[i] != '_') {
+ if (name[i] >= 'A' && name[i] <= 'Z') {
+ result.push_back(name[i] - 'A' + 'a');
+ } else {
+ result.push_back(name[i]);
+ }
+ }
+ }
+ return result;
+}
+
void DescriptorBuilder::ValidateProto3Message(
Descriptor* message, const DescriptorProto& proto) {
for (int i = 0; i < message->nested_type_count(); ++i) {
@@ -5067,6 +5132,25 @@ void DescriptorBuilder::ValidateProto3Message(
DescriptorPool::ErrorCollector::OTHER,
"MessageSet is not supported in proto3.");
}
+
+ // In proto3, we reject field names if they conflict in camelCase.
+ // Note that we currently enforce a stricter rule: Field names must be
+ // unique after being converted to lowercase with underscores removed.
+ map<string, const FieldDescriptor*> name_to_field;
+ for (int i = 0; i < message->field_count(); ++i) {
+ string lowercase_name = ToLowercaseWithoutUnderscores(
+ message->field(i)->name());
+ if (name_to_field.find(lowercase_name) != name_to_field.end()) {
+ AddError(message->full_name(), proto,
+ DescriptorPool::ErrorCollector::OTHER,
+ "The JSON camcel-case name of field \"" +
+ message->field(i)->name() + "\" conflicts with field \"" +
+ name_to_field[lowercase_name]->name() + "\". This is not " +
+ "allowed in proto3.");
+ } else {
+ name_to_field[lowercase_name] = message->field(i);
+ }
+ }
}
void DescriptorBuilder::ValidateProto3Field(
@@ -5602,7 +5686,7 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
// First set the value on the UnknownFieldSet corresponding to the
// innermost message.
- scoped_ptr<UnknownFieldSet> unknown_fields(new UnknownFieldSet());
+ google::protobuf::scoped_ptr<UnknownFieldSet> unknown_fields(new UnknownFieldSet());
if (!SetOptionValue(field, unknown_fields.get())) {
return false; // SetOptionValue() already added the error.
}
@@ -5612,7 +5696,8 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
for (vector<const FieldDescriptor*>::reverse_iterator iter =
intermediate_fields.rbegin();
iter != intermediate_fields.rend(); ++iter) {
- scoped_ptr<UnknownFieldSet> parent_unknown_fields(new UnknownFieldSet());
+ google::protobuf::scoped_ptr<UnknownFieldSet> parent_unknown_fields(
+ new UnknownFieldSet());
switch ((*iter)->type()) {
case FieldDescriptor::TYPE_MESSAGE: {
io::StringOutputStream outstr(
@@ -5998,7 +6083,7 @@ bool DescriptorBuilder::OptionInterpreter::SetAggregateOption(
}
const Descriptor* type = option_field->message_type();
- scoped_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New());
+ google::protobuf::scoped_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New());
GOOGLE_CHECK(dynamic.get() != NULL)
<< "Could not create an instance of " << option_field->DebugString();
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 2ab316a5..e7e8c6af 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -54,6 +54,10 @@
#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H__
#define GOOGLE_PROTOBUF_DESCRIPTOR_H__
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <set>
#include <string>
#include <vector>
@@ -111,8 +115,17 @@ class UnknownField;
// Defined in generated_message_reflection.h.
namespace internal {
- class GeneratedMessageReflection;
-}
+class GeneratedMessageReflection;
+} // namespace internal
+
+// Defined in command_line_interface.cc
+namespace compiler {
+class CommandLineInterface;
+} // namespace compiler
+
+namespace descriptor_unittest {
+class DescriptorTest;
+} // namespace descriptor_unittest
// NB, all indices are zero-based.
struct SourceLocation {
@@ -343,6 +356,12 @@ class LIBPROTOBUF_EXPORT Descriptor {
private:
typedef MessageOptions OptionsType;
+ // Allows tests to test CopyTo(proto, true).
+ friend class ::google::protobuf::descriptor_unittest::DescriptorTest;
+
+ // Fill the json_name field of FieldDescriptorProto.
+ void CopyJsonNameTo(DescriptorProto* proto) const;
+
// Internal version of DebugString; controls the level of indenting for
// correct depth. Takes |options| to control debug-string options, and
// |include_opening_clause| to indicate whether the "message ... " part of the
@@ -484,6 +503,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
const string& name() const; // Name of this field within the message.
const string& full_name() const; // Fully-qualified name of the field.
+ const string& json_name() const; // JSON name of this field.
const FileDescriptor* file() const;// File in which this field was defined.
bool is_extension() const; // Is this an extension field?
int number() const; // Declared tag number.
@@ -624,6 +644,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
private:
typedef FieldOptions OptionsType;
+ // Fill the json_name field of FieldDescriptorProto.
+ void CopyJsonNameTo(FieldDescriptorProto* proto) const;
+
// See Descriptor::DebugString().
enum PrintLabelFlag { PRINT_LABEL, OMIT_LABEL };
void DebugString(int depth, PrintLabelFlag print_label_flag,
@@ -645,6 +668,12 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
const string* full_name_;
const string* lowercase_name_;
const string* camelcase_name_;
+ // Whether the user has specified the json_name field option in the .proto
+ // file.
+ bool has_json_name_;
+ // If has_json_name_ is true, it's the value specified by the user.
+ // Otherwise, it has the same value as lowercase_name_.
+ const string* json_name_;
const FileDescriptor* file_;
int number_;
Type type_;
@@ -1202,6 +1231,9 @@ class LIBPROTOBUF_EXPORT FileDescriptor {
// Write the source code information of this FileDescriptor into the given
// FileDescriptorProto. See CopyTo() above.
void CopySourceCodeInfoTo(FileDescriptorProto* proto) const;
+ // Fill the json_name field of FieldDescriptorProto for all fields. Can only
+ // be called after CopyTo().
+ void CopyJsonNameTo(FileDescriptorProto* proto) const;
// See Descriptor::DebugString().
string DebugString() const;
@@ -1559,7 +1591,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
// This class contains a lot of hash maps with complicated types that
// we'd like to keep out of the header.
class Tables;
- scoped_ptr<Tables> tables_;
+ google::protobuf::scoped_ptr<Tables> tables_;
bool enforce_dependencies_;
bool allow_unknown_;
@@ -1618,6 +1650,7 @@ PROTOBUF_DEFINE_ACCESSOR(Descriptor, is_placeholder, bool)
PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, name)
PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, full_name)
+PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, json_name)
PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, lowercase_name)
PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, camelcase_name)
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, file, const FileDescriptor*)
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index fe23c0ab..9c817122 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -200,7 +200,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, _internal_metadata_),
-1);
FieldDescriptorProto_descriptor_ = file->message_type(3);
- static const int FieldDescriptorProto_offsets_[9] = {
+ static const int FieldDescriptorProto_offsets_[10] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, number_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, label_),
@@ -209,6 +209,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, extendee_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, default_value_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, oneof_index_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, json_name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, options_),
};
FieldDescriptorProto_reflection_ =
@@ -663,101 +664,102 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"tobuf.DescriptorProto.ReservedRange\022\025\n\rr"
"eserved_name\030\n \003(\t\032,\n\016ExtensionRange\022\r\n\005"
"start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\032+\n\rReservedRang"
- "e\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\251\005\n\024FieldD"
+ "e\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\274\005\n\024FieldD"
"escriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\003"
" \001(\005\022:\n\005label\030\004 \001(\0162+.google.protobuf.Fi"
"eldDescriptorProto.Label\0228\n\004type\030\005 \001(\0162*"
".google.protobuf.FieldDescriptorProto.Ty"
"pe\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010extendee\030\002 \001(\t\022"
"\025\n\rdefault_value\030\007 \001(\t\022\023\n\013oneof_index\030\t "
- "\001(\005\022.\n\007options\030\010 \001(\0132\035.google.protobuf.F"
- "ieldOptions\"\266\002\n\004Type\022\017\n\013TYPE_DOUBLE\020\001\022\016\n"
- "\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYPE_UI"
- "NT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED64\020\006"
- "\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022\017\n\013TYP"
- "E_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_MESSA"
- "GE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020\r\022\r\n"
- "\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rTYPE_"
- "SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_SINT"
- "64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n\016LAB"
- "EL_REQUIRED\020\002\022\022\n\016LABEL_REPEATED\020\003\"$\n\024One"
- "ofDescriptorProto\022\014\n\004name\030\001 \001(\t\"\214\001\n\023Enum"
- "DescriptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005value\030\002"
- " \003(\0132).google.protobuf.EnumValueDescript"
- "orProto\022-\n\007options\030\003 \001(\0132\034.google.protob"
- "uf.EnumOptions\"l\n\030EnumValueDescriptorPro"
- "to\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007opti"
- "ons\030\003 \001(\0132!.google.protobuf.EnumValueOpt"
- "ions\"\220\001\n\026ServiceDescriptorProto\022\014\n\004name\030"
- "\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.protobuf."
- "MethodDescriptorProto\0220\n\007options\030\003 \001(\0132\037"
- ".google.protobuf.ServiceOptions\"\301\001\n\025Meth"
- "odDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\ninput"
- "_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n\007opti"
- "ons\030\004 \001(\0132\036.google.protobuf.MethodOption"
- "s\022\037\n\020client_streaming\030\005 \001(\010:\005false\022\037\n\020se"
- "rver_streaming\030\006 \001(\010:\005false\"\252\005\n\013FileOpti"
- "ons\022\024\n\014java_package\030\001 \001(\t\022\034\n\024java_outer_"
- "classname\030\010 \001(\t\022\"\n\023java_multiple_files\030\n"
- " \001(\010:\005false\022,\n\035java_generate_equals_and_"
- "hash\030\024 \001(\010:\005false\022%\n\026java_string_check_u"
- "tf8\030\033 \001(\010:\005false\022F\n\014optimize_for\030\t \001(\0162)"
- ".google.protobuf.FileOptions.OptimizeMod"
- "e:\005SPEED\022\022\n\ngo_package\030\013 \001(\t\022\"\n\023cc_gener"
- "ic_services\030\020 \001(\010:\005false\022$\n\025java_generic"
- "_services\030\021 \001(\010:\005false\022\"\n\023py_generic_ser"
- "vices\030\022 \001(\010:\005false\022\031\n\ndeprecated\030\027 \001(\010:\005"
- "false\022\037\n\020cc_enable_arenas\030\037 \001(\010:\005false\022\031"
- "\n\021objc_class_prefix\030$ \001(\t\022\030\n\020csharp_name"
- "space\030% \001(\t\022\'\n\037javanano_use_deprecated_p"
- "ackage\030& \001(\010\022C\n\024uninterpreted_option\030\347\007 "
- "\003(\0132$.google.protobuf.UninterpretedOptio"
- "n\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZ"
- "E\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016Mes"
- "sageOptions\022&\n\027message_set_wire_format\030\001"
- " \001(\010:\005false\022.\n\037no_standard_descriptor_ac"
- "cessor\030\002 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:"
- "\005false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024uninterpret"
- "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint"
- "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"\230\003\n\014FieldOptio"
- "ns\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Fiel"
- "dOptions.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\?"
- "\n\006jstype\030\006 \001(\0162$.google.protobuf.FieldOp"
- "tions.JSType:\tJS_NORMAL\022\023\n\004lazy\030\005 \001(\010:\005f"
- "alse\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\023\n\004weak\030"
- "\n \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 "
- "\003(\0132$.google.protobuf.UninterpretedOptio"
- "n\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRI"
- "NG_PIECE\020\002\"5\n\006JSType\022\r\n\tJS_NORMAL\020\000\022\r\n\tJ"
- "S_STRING\020\001\022\r\n\tJS_NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n"
- "\013EnumOptions\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndep"
- "recated\030\003 \001(\010:\005false\022C\n\024uninterpreted_op"
- "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre"
- "tedOption*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueOptions"
- "\022\031\n\ndeprecated\030\001 \001(\010:\005false\022C\n\024uninterpr"
- "eted_option\030\347\007 \003(\0132$.google.protobuf.Uni"
- "nterpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOp"
- "tions\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024unin"
- "terpreted_option\030\347\007 \003(\0132$.google.protobu"
- "f.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMeth"
- "odOptions\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024"
- "uninterpreted_option\030\347\007 \003(\0132$.google.pro"
- "tobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n"
- "\023UninterpretedOption\022;\n\004name\030\002 \003(\0132-.goo"
- "gle.protobuf.UninterpretedOption.NamePar"
- "t\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022positive_"
- "int_value\030\004 \001(\004\022\032\n\022negative_int_value\030\005 "
- "\001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014string_valu"
- "e\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010Name"
- "Part\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extension\030"
- "\002 \002(\010\"\325\001\n\016SourceCodeInfo\022:\n\010location\030\001 \003"
- "(\0132(.google.protobuf.SourceCodeInfo.Loca"
- "tion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004s"
- "pan\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022"
- "\031\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_de"
- "tached_comments\030\006 \003(\tB;\n\023com.google.prot"
- "obufB\020DescriptorProtosH\001Z\ndescriptor\242\002\003G"
- "PB", 4962);
+ "\001(\005\022\021\n\tjson_name\030\n \001(\t\022.\n\007options\030\010 \001(\0132"
+ "\035.google.protobuf.FieldOptions\"\266\002\n\004Type\022"
+ "\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE"
+ "_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32\020"
+ "\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n"
+ "\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_GR"
+ "OUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022"
+ "\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_"
+ "SFIXED32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_SI"
+ "NT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005Label\022\022\n\016LABE"
+ "L_OPTIONAL\020\001\022\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LABE"
+ "L_REPEATED\020\003\"$\n\024OneofDescriptorProto\022\014\n\004"
+ "name\030\001 \001(\t\"\214\001\n\023EnumDescriptorProto\022\014\n\004na"
+ "me\030\001 \001(\t\0228\n\005value\030\002 \003(\0132).google.protobu"
+ "f.EnumValueDescriptorProto\022-\n\007options\030\003 "
+ "\001(\0132\034.google.protobuf.EnumOptions\"l\n\030Enu"
+ "mValueDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006n"
+ "umber\030\002 \001(\005\0222\n\007options\030\003 \001(\0132!.google.pr"
+ "otobuf.EnumValueOptions\"\220\001\n\026ServiceDescr"
+ "iptorProto\022\014\n\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\013"
+ "2&.google.protobuf.MethodDescriptorProto"
+ "\0220\n\007options\030\003 \001(\0132\037.google.protobuf.Serv"
+ "iceOptions\"\301\001\n\025MethodDescriptorProto\022\014\n\004"
+ "name\030\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023\n\013output"
+ "_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.pr"
+ "otobuf.MethodOptions\022\037\n\020client_streaming"
+ "\030\005 \001(\010:\005false\022\037\n\020server_streaming\030\006 \001(\010:"
+ "\005false\"\252\005\n\013FileOptions\022\024\n\014java_package\030\001"
+ " \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023ja"
+ "va_multiple_files\030\n \001(\010:\005false\022,\n\035java_g"
+ "enerate_equals_and_hash\030\024 \001(\010:\005false\022%\n\026"
+ "java_string_check_utf8\030\033 \001(\010:\005false\022F\n\014o"
+ "ptimize_for\030\t \001(\0162).google.protobuf.File"
+ "Options.OptimizeMode:\005SPEED\022\022\n\ngo_packag"
+ "e\030\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001(\010:\005fa"
+ "lse\022$\n\025java_generic_services\030\021 \001(\010:\005fals"
+ "e\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031\n"
+ "\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enable_ar"
+ "enas\030\037 \001(\010:\005false\022\031\n\021objc_class_prefix\030$"
+ " \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022\'\n\037javana"
+ "no_use_deprecated_package\030& \001(\010\022C\n\024unint"
+ "erpreted_option\030\347\007 \003(\0132$.google.protobuf"
+ ".UninterpretedOption\":\n\014OptimizeMode\022\t\n\005"
+ "SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003"
+ "*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016MessageOptions\022&\n\027messag"
+ "e_set_wire_format\030\001 \001(\010:\005false\022.\n\037no_sta"
+ "ndard_descriptor_accessor\030\002 \001(\010:\005false\022\031"
+ "\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tmap_entry\030\007"
+ " \001(\010\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go"
+ "ogle.protobuf.UninterpretedOption*\t\010\350\007\020\200"
+ "\200\200\200\002\"\230\003\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#.g"
+ "oogle.protobuf.FieldOptions.CType:\006STRIN"
+ "G\022\016\n\006packed\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$.goog"
+ "le.protobuf.FieldOptions.JSType:\tJS_NORM"
+ "AL\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecated\030\003 "
+ "\001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024unint"
+ "erpreted_option\030\347\007 \003(\0132$.google.protobuf"
+ ".UninterpretedOption\"/\n\005CType\022\n\n\006STRING\020"
+ "\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002\"5\n\006JSType\022"
+ "\r\n\tJS_NORMAL\020\000\022\r\n\tJS_STRING\020\001\022\r\n\tJS_NUMB"
+ "ER\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023\n\013allow"
+ "_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005false\022"
+ "C\n\024uninterpreted_option\030\347\007 \003(\0132$.google."
+ "protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\""
+ "}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001 \001(\010:"
+ "\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$."
+ "google.protobuf.UninterpretedOption*\t\010\350\007"
+ "\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndeprecated\030!"
+ " \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003"
+ "(\0132$.google.protobuf.UninterpretedOption"
+ "*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndeprecat"
+ "ed\030! \001(\010:\005false\022C\n\024uninterpreted_option\030"
+ "\347\007 \003(\0132$.google.protobuf.UninterpretedOp"
+ "tion*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOption\022"
+ ";\n\004name\030\002 \003(\0132-.google.protobuf.Uninterp"
+ "retedOption.NamePart\022\030\n\020identifier_value"
+ "\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022ne"
+ "gative_int_value\030\005 \001(\003\022\024\n\014double_value\030\006"
+ " \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggregate_"
+ "value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part\030\001 \002"
+ "(\t\022\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016SourceCodeI"
+ "nfo\022:\n\010location\030\001 \003(\0132(.google.protobuf."
+ "SourceCodeInfo.Location\032\206\001\n\010Location\022\020\n\004"
+ "path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020lead"
+ "ing_comments\030\003 \001(\t\022\031\n\021trailing_comments\030"
+ "\004 \001(\t\022!\n\031leading_detached_comments\030\006 \003(\t"
+ "BX\n\023com.google.protobufB\020DescriptorProto"
+ "sH\001Z\ndescriptor\242\002\003GPB\252\002\032Google.Protobuf."
+ "Reflection", 5010);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -4109,6 +4111,7 @@ const int FieldDescriptorProto::kTypeNameFieldNumber;
const int FieldDescriptorProto::kExtendeeFieldNumber;
const int FieldDescriptorProto::kDefaultValueFieldNumber;
const int FieldDescriptorProto::kOneofIndexFieldNumber;
+const int FieldDescriptorProto::kJsonNameFieldNumber;
const int FieldDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
@@ -4141,6 +4144,7 @@ void FieldDescriptorProto::SharedCtor() {
extendee_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
default_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
oneof_index_ = 0;
+ json_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
options_ = NULL;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -4155,6 +4159,7 @@ void FieldDescriptorProto::SharedDtor() {
type_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
extendee_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
default_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ json_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (this != default_instance_) {
delete options_;
}
@@ -4204,8 +4209,13 @@ void FieldDescriptorProto::Clear() {
}
oneof_index_ = 0;
}
- if (has_options()) {
- if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
+ if (_has_bits_[8 / 32] & 768u) {
+ if (has_json_name()) {
+ json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ if (has_options()) {
+ if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
+ }
}
::memset(_has_bits_, 0, sizeof(_has_bits_));
if (_internal_metadata_.have_unknown_fields()) {
@@ -4369,6 +4379,23 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
+ if (input->ExpectTag(82)) goto parse_json_name;
+ break;
+ }
+
+ // optional string json_name = 10;
+ case 10: {
+ if (tag == 82) {
+ parse_json_name:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_json_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->json_name().data(), this->json_name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.FieldDescriptorProto.json_name");
+ } else {
+ goto handle_unusual;
+ }
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -4466,6 +4493,16 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteInt32(9, this->oneof_index(), output);
}
+ // optional string json_name = 10;
+ if (has_json_name()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->json_name().data(), this->json_name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.FieldDescriptorProto.json_name");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 10, this->json_name(), output);
+ }
+
if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
@@ -4549,6 +4586,17 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(9, this->oneof_index(), target);
}
+ // optional string json_name = 10;
+ if (has_json_name()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->json_name().data(), this->json_name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.FieldDescriptorProto.json_name");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 10, this->json_name(), target);
+ }
+
if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -4616,13 +4664,22 @@ int FieldDescriptorProto::ByteSize() const {
}
}
- // optional .google.protobuf.FieldOptions options = 8;
- if (has_options()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
- *this->options_);
- }
+ if (_has_bits_[8 / 32] & 768u) {
+ // optional string json_name = 10;
+ if (has_json_name()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->json_name());
+ }
+ // optional .google.protobuf.FieldOptions options = 8;
+ if (has_options()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ *this->options_);
+ }
+
+ }
if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
@@ -4679,6 +4736,10 @@ void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) {
}
}
if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+ if (from.has_json_name()) {
+ set_has_json_name();
+ json_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.json_name_);
+ }
if (from.has_options()) {
mutable_options()->::google::protobuf::FieldOptions::MergeFrom(from.options());
}
@@ -4721,6 +4782,7 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
extendee_.Swap(&other->extendee_);
default_value_.Swap(&other->default_value_);
std::swap(oneof_index_, other->oneof_index_);
+ json_name_.Swap(&other->json_name_);
std::swap(options_, other->options_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_internal_metadata_.Swap(&other->_internal_metadata_);
@@ -5048,15 +5110,68 @@ void FieldDescriptorProto::clear_oneof_index() {
// @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index)
}
+// optional string json_name = 10;
+bool FieldDescriptorProto::has_json_name() const {
+ return (_has_bits_[0] & 0x00000100u) != 0;
+}
+void FieldDescriptorProto::set_has_json_name() {
+ _has_bits_[0] |= 0x00000100u;
+}
+void FieldDescriptorProto::clear_has_json_name() {
+ _has_bits_[0] &= ~0x00000100u;
+}
+void FieldDescriptorProto::clear_json_name() {
+ json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_json_name();
+}
+ const ::std::string& FieldDescriptorProto::json_name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.json_name)
+ return json_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_json_name(const ::std::string& value) {
+ set_has_json_name();
+ json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.json_name)
+}
+ void FieldDescriptorProto::set_json_name(const char* value) {
+ set_has_json_name();
+ json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.json_name)
+}
+ void FieldDescriptorProto::set_json_name(const char* value, size_t size) {
+ set_has_json_name();
+ json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.json_name)
+}
+ ::std::string* FieldDescriptorProto::mutable_json_name() {
+ set_has_json_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.json_name)
+ return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_json_name() {
+ clear_has_json_name();
+ return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_json_name(::std::string* json_name) {
+ if (json_name != NULL) {
+ set_has_json_name();
+ } else {
+ clear_has_json_name();
+ }
+ json_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), json_name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.json_name)
+}
+
// optional .google.protobuf.FieldOptions options = 8;
bool FieldDescriptorProto::has_options() const {
- return (_has_bits_[0] & 0x00000100u) != 0;
+ return (_has_bits_[0] & 0x00000200u) != 0;
}
void FieldDescriptorProto::set_has_options() {
- _has_bits_[0] |= 0x00000100u;
+ _has_bits_[0] |= 0x00000200u;
}
void FieldDescriptorProto::clear_has_options() {
- _has_bits_[0] &= ~0x00000100u;
+ _has_bits_[0] &= ~0x00000200u;
}
void FieldDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 931ff02d..60255162 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -1133,6 +1133,18 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
::google::protobuf::int32 oneof_index() const;
void set_oneof_index(::google::protobuf::int32 value);
+ // optional string json_name = 10;
+ bool has_json_name() const;
+ void clear_json_name();
+ static const int kJsonNameFieldNumber = 10;
+ const ::std::string& json_name() const;
+ void set_json_name(const ::std::string& value);
+ void set_json_name(const char* value);
+ void set_json_name(const char* value, size_t size);
+ ::std::string* mutable_json_name();
+ ::std::string* release_json_name();
+ void set_allocated_json_name(::std::string* json_name);
+
// optional .google.protobuf.FieldOptions options = 8;
bool has_options() const;
void clear_options();
@@ -1160,6 +1172,8 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
inline void clear_has_default_value();
inline void set_has_oneof_index();
inline void clear_has_oneof_index();
+ inline void set_has_json_name();
+ inline void clear_has_json_name();
inline void set_has_options();
inline void clear_has_options();
@@ -1174,6 +1188,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
int type_;
::google::protobuf::int32 oneof_index_;
::google::protobuf::internal::ArenaStringPtr default_value_;
+ ::google::protobuf::internal::ArenaStringPtr json_name_;
::google::protobuf::FieldOptions* options_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
@@ -4678,15 +4693,68 @@ inline void FieldDescriptorProto::set_oneof_index(::google::protobuf::int32 valu
// @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index)
}
+// optional string json_name = 10;
+inline bool FieldDescriptorProto::has_json_name() const {
+ return (_has_bits_[0] & 0x00000100u) != 0;
+}
+inline void FieldDescriptorProto::set_has_json_name() {
+ _has_bits_[0] |= 0x00000100u;
+}
+inline void FieldDescriptorProto::clear_has_json_name() {
+ _has_bits_[0] &= ~0x00000100u;
+}
+inline void FieldDescriptorProto::clear_json_name() {
+ json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_json_name();
+}
+inline const ::std::string& FieldDescriptorProto::json_name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.json_name)
+ return json_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FieldDescriptorProto::set_json_name(const ::std::string& value) {
+ set_has_json_name();
+ json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.json_name)
+}
+inline void FieldDescriptorProto::set_json_name(const char* value) {
+ set_has_json_name();
+ json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.json_name)
+}
+inline void FieldDescriptorProto::set_json_name(const char* value, size_t size) {
+ set_has_json_name();
+ json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.json_name)
+}
+inline ::std::string* FieldDescriptorProto::mutable_json_name() {
+ set_has_json_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.json_name)
+ return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FieldDescriptorProto::release_json_name() {
+ clear_has_json_name();
+ return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FieldDescriptorProto::set_allocated_json_name(::std::string* json_name) {
+ if (json_name != NULL) {
+ set_has_json_name();
+ } else {
+ clear_has_json_name();
+ }
+ json_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), json_name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.json_name)
+}
+
// optional .google.protobuf.FieldOptions options = 8;
inline bool FieldDescriptorProto::has_options() const {
- return (_has_bits_[0] & 0x00000100u) != 0;
+ return (_has_bits_[0] & 0x00000200u) != 0;
}
inline void FieldDescriptorProto::set_has_options() {
- _has_bits_[0] |= 0x00000100u;
+ _has_bits_[0] |= 0x00000200u;
}
inline void FieldDescriptorProto::clear_has_options() {
- _has_bits_[0] &= ~0x00000100u;
+ _has_bits_[0] &= ~0x00000200u;
}
inline void FieldDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index 8f90a956..c59a6022 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -43,8 +43,7 @@ package google.protobuf;
option go_package = "descriptor";
option java_package = "com.google.protobuf";
option java_outer_classname = "DescriptorProtos";
-// Re-enable this once the tools have picked up the csharp_namespace option.
-// option csharp_namespace = "Google.ProtocolBuffers.DescriptorProtos";
+option csharp_namespace = "Google.Protobuf.Reflection";
option objc_class_prefix = "GPB";
// descriptor.proto must be optimized for speed because reflection-based
@@ -191,6 +190,12 @@ message FieldDescriptorProto {
// list. This field is a member of that oneof.
optional int32 oneof_index = 9;
+ // JSON name of this field. The value is set by protocol compiler. If the
+ // user has set a "json_name" option on this field, that option's value
+ // will be used. Otherwise, it's deduced from the field's name by converting
+ // it to camelCase.
+ optional string json_name = 10;
+
optional FieldOptions options = 8;
}
diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc
index a87fa049..1fc3816e 100644
--- a/src/google/protobuf/descriptor_database_unittest.cc
+++ b/src/google/protobuf/descriptor_database_unittest.cc
@@ -35,6 +35,10 @@
// This file makes extensive use of RFC 3092. :)
#include <algorithm>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/descriptor_database.h>
#include <google/protobuf/descriptor.h>
@@ -177,7 +181,7 @@ class DescriptorDatabaseTest
EXPECT_FALSE(test_case_->AddToDatabase(file_proto));
}
- scoped_ptr<DescriptorDatabaseTestCase> test_case_;
+ google::protobuf::scoped_ptr<DescriptorDatabaseTestCase> test_case_;
DescriptorDatabase* database_;
};
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index e9b027db..ccd0650d 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -34,6 +34,10 @@
//
// This file makes extensive use of RFC 3092. :)
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <vector>
#include <google/protobuf/compiler/importer.h>
@@ -461,6 +465,16 @@ class DescriptorTest : public testing::Test {
// map<int32, int32> map_int32_int32 = 1;
// }
//
+ // // in "json.proto"
+ // message TestMessage4 {
+ // optional int32 field_name1 = 1;
+ // optional int32 fieldName2 = 2;
+ // optional int32 FieldName3 = 3;
+ // optional int32 _field_name4 = 4;
+ // optional int32 FIELD_NAME5 = 5;
+ // optional int32 field_name6 = 6 [json_name = "@type"];
+ // }
+ //
// We cheat and use TestForeign as the type for qux rather than create
// an actual nested type.
//
@@ -526,6 +540,30 @@ class DescriptorTest : public testing::Test {
FieldDescriptorProto::TYPE_MESSAGE)
->set_type_name("MapInt32Int32Entry");
+ FileDescriptorProto json_file;
+ json_file.set_name("json.proto");
+ json_file.set_syntax("proto3");
+ DescriptorProto* message4 = AddMessage(&json_file, "TestMessage4");
+ AddField(message4, "field_name1", 1,
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddField(message4, "fieldName2", 2,
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddField(message4, "FieldName3", 3,
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddField(message4, "_field_name4", 4,
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddField(message4, "FIELD_NAME5", 5,
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32);
+ AddField(message4, "field_name6", 6,
+ FieldDescriptorProto::LABEL_OPTIONAL,
+ FieldDescriptorProto::TYPE_INT32)
+ ->set_json_name("@type");
+
// Build the descriptors and get the pointers.
foo_file_ = pool_.BuildFile(foo_file);
ASSERT_TRUE(foo_file_ != NULL);
@@ -536,6 +574,9 @@ class DescriptorTest : public testing::Test {
map_file_ = pool_.BuildFile(map_file);
ASSERT_TRUE(map_file_ != NULL);
+ json_file_ = pool_.BuildFile(json_file);
+ ASSERT_TRUE(json_file_ != NULL);
+
ASSERT_EQ(1, foo_file_->enum_type_count());
enum_ = foo_file_->enum_type(0);
@@ -562,6 +603,14 @@ class DescriptorTest : public testing::Test {
ASSERT_EQ(1, message3_->field_count());
map_ = message3_->field(0);
+
+ ASSERT_EQ(1, json_file_->message_type_count());
+ message4_ = json_file_->message_type(0);
+ }
+
+ void CopyWithJsonName(const Descriptor* message, DescriptorProto* proto) {
+ message->CopyTo(proto);
+ message->CopyJsonNameTo(proto);
}
DescriptorPool pool_;
@@ -569,10 +618,12 @@ class DescriptorTest : public testing::Test {
const FileDescriptor* foo_file_;
const FileDescriptor* bar_file_;
const FileDescriptor* map_file_;
+ const FileDescriptor* json_file_;
const Descriptor* message_;
const Descriptor* message2_;
const Descriptor* message3_;
+ const Descriptor* message4_;
const Descriptor* foreign_;
const EnumDescriptor* enum_;
@@ -664,6 +715,35 @@ TEST_F(DescriptorTest, FieldFullName) {
EXPECT_EQ("corge.grault.TestMessage2.quux", quux2_->full_name());
}
+TEST_F(DescriptorTest, FieldJsonName) {
+ EXPECT_EQ("fieldName1", message4_->field(0)->json_name());
+ EXPECT_EQ("fieldName2", message4_->field(1)->json_name());
+ EXPECT_EQ("fieldName3", message4_->field(2)->json_name());
+ EXPECT_EQ("fieldName4", message4_->field(3)->json_name());
+ EXPECT_EQ("fIELDNAME5", message4_->field(4)->json_name());
+ EXPECT_EQ("@type", message4_->field(5)->json_name());
+
+ DescriptorProto proto;
+ message4_->CopyTo(&proto);
+ ASSERT_EQ(6, proto.field_size());
+ EXPECT_FALSE(proto.field(0).has_json_name());
+ EXPECT_FALSE(proto.field(1).has_json_name());
+ EXPECT_FALSE(proto.field(2).has_json_name());
+ EXPECT_FALSE(proto.field(3).has_json_name());
+ EXPECT_FALSE(proto.field(4).has_json_name());
+ EXPECT_EQ("@type", proto.field(5).json_name());
+
+ proto.Clear();
+ CopyWithJsonName(message4_, &proto);
+ ASSERT_EQ(6, proto.field_size());
+ EXPECT_EQ("fieldName1", proto.field(0).json_name());
+ EXPECT_EQ("fieldName2", proto.field(1).json_name());
+ EXPECT_EQ("fieldName3", proto.field(2).json_name());
+ EXPECT_EQ("fieldName4", proto.field(3).json_name());
+ EXPECT_EQ("fIELDNAME5", proto.field(4).json_name());
+ EXPECT_EQ("@type", proto.field(5).json_name());
+}
+
TEST_F(DescriptorTest, FieldFile) {
EXPECT_EQ(foo_file_, foo_->file());
EXPECT_EQ(foo_file_, bar_->file());
@@ -1900,7 +1980,7 @@ class MiscTest : public testing::Test {
return field != NULL ? field->enum_type() : NULL;
}
- scoped_ptr<DescriptorPool> pool_;
+ google::protobuf::scoped_ptr<DescriptorPool> pool_;
};
TEST_F(MiscTest, TypeNames) {
@@ -2330,7 +2410,7 @@ class AllowUnknownDependenciesTest
const FieldDescriptor* qux_field_;
SimpleDescriptorDatabase db_; // used if in FALLBACK_DATABASE mode.
- scoped_ptr<DescriptorPool> pool_;
+ google::protobuf::scoped_ptr<DescriptorPool> pool_;
};
TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) {
@@ -5681,6 +5761,32 @@ TEST_F(ValidationErrorTest, ValidateProto3Extension) {
"defining options.\n");
}
+// Test that field names that may conflict in JSON is not allowed by protoc.
+TEST_F(ValidationErrorTest, ValidateProto3JsonName) {
+ // The comparison is case-insensitive.
+ BuildFileWithErrors(
+ "name: 'foo.proto' "
+ "syntax: 'proto3' "
+ "message_type {"
+ " name: 'Foo'"
+ " field { name:'name' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ " field { name:'Name' number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ "}",
+ "foo.proto: Foo: OTHER: The JSON camcel-case name of field \"Name\" "
+ "conflicts with field \"name\". This is not allowed in proto3.\n");
+ // Underscores are ignored.
+ BuildFileWithErrors(
+ "name: 'foo.proto' "
+ "syntax: 'proto3' "
+ "message_type {"
+ " name: 'Foo'"
+ " field { name:'ab' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ " field { name:'_a__b_' number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ "}",
+ "foo.proto: Foo: OTHER: The JSON camcel-case name of field \"_a__b_\" "
+ "conflicts with field \"ab\". This is not allowed in proto3.\n");
+}
+
// ===================================================================
// DescriptorDatabase
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index 2324d952..091fc975 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -64,6 +64,10 @@
#include <algorithm>
#include <google/protobuf/stubs/hash.h>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/stubs/common.h>
@@ -229,8 +233,8 @@ class DynamicMessage : public Message {
// Warning: The order in which the following pointers are defined is
// important (the prototype must be deleted *before* the offsets).
- scoped_array<int> offsets;
- scoped_ptr<const GeneratedMessageReflection> reflection;
+ google::protobuf::scoped_array<int> offsets;
+ google::protobuf::scoped_ptr<const GeneratedMessageReflection> reflection;
// Don't use a scoped_ptr to hold the prototype: the destructor for
// DynamicMessage needs to know whether it is the prototype, and does so by
// looking back at this field. This would assume details about the
diff --git a/src/google/protobuf/dynamic_message_unittest.cc b/src/google/protobuf/dynamic_message_unittest.cc
index b9796c76..70e437d7 100644
--- a/src/google/protobuf/dynamic_message_unittest.cc
+++ b/src/google/protobuf/dynamic_message_unittest.cc
@@ -40,6 +40,11 @@
// reflection_ops_unittest, cover the rest of the functionality used by
// DynamicMessage.
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/dynamic_message.h>
@@ -144,7 +149,7 @@ TEST_F(DynamicMessageTest, IndependentOffsets) {
// Check that all fields have independent offsets by setting each
// 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> message(prototype_->New());
+ google::protobuf::scoped_ptr<Message> message(prototype_->New());
TestUtil::ReflectionTester reflection_tester(descriptor_);
reflection_tester.SetAllFieldsViaReflection(message.get());
@@ -153,7 +158,7 @@ TEST_F(DynamicMessageTest, IndependentOffsets) {
TEST_F(DynamicMessageTest, Extensions) {
// Check that extensions work.
- scoped_ptr<Message> message(extensions_prototype_->New());
+ google::protobuf::scoped_ptr<Message> message(extensions_prototype_->New());
TestUtil::ReflectionTester reflection_tester(extensions_descriptor_);
reflection_tester.SetAllFieldsViaReflection(message.get());
@@ -162,7 +167,7 @@ TEST_F(DynamicMessageTest, Extensions) {
TEST_F(DynamicMessageTest, PackedFields) {
// Check that packed fields work properly.
- scoped_ptr<Message> message(packed_prototype_->New());
+ google::protobuf::scoped_ptr<Message> message(packed_prototype_->New());
TestUtil::ReflectionTester reflection_tester(packed_descriptor_);
reflection_tester.SetPackedFieldsViaReflection(message.get());
@@ -171,7 +176,7 @@ TEST_F(DynamicMessageTest, PackedFields) {
TEST_F(DynamicMessageTest, Oneof) {
// Check that oneof fields work properly.
- scoped_ptr<Message> message(oneof_prototype_->New());
+ google::protobuf::scoped_ptr<Message> message(oneof_prototype_->New());
// Check default values.
const Descriptor* descriptor = message->GetDescriptor();
@@ -232,7 +237,7 @@ TEST_F(DynamicMessageTest, SpaceUsed) {
// Since we share the implementation with generated messages, we don't need
// to test very much here. Just make sure it appears to be working.
- scoped_ptr<Message> message(prototype_->New());
+ google::protobuf::scoped_ptr<Message> message(prototype_->New());
TestUtil::ReflectionTester reflection_tester(descriptor_);
int initial_space_used = message->SpaceUsed();
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index 919bd83b..9afb2361 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/stubs/hash.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/message_lite.h>
#include <google/protobuf/io/coded_stream.h>
@@ -594,20 +595,21 @@ void ExtensionSet::SetAllocatedMessage(int number, FieldType type,
ClearExtension(number);
return;
}
+ ::google::protobuf::Arena* message_arena = message->GetArena();
Extension* extension;
if (MaybeNewExtension(number, descriptor, &extension)) {
extension->type = type;
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
extension->is_repeated = false;
extension->is_lazy = false;
- if (message->GetArena() == arena_) {
+ if (message_arena == arena_) {
extension->message_value = message;
+ } else if (message_arena == NULL) {
+ extension->message_value = message;
+ arena_->Own(message); // not NULL because not equal to message_arena
} else {
extension->message_value = message->New(arena_);
extension->message_value->CheckTypeAndMergeFrom(*message);
- if (message->GetArena() == NULL) {
- delete message;
- }
}
} else {
GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
@@ -617,14 +619,14 @@ void ExtensionSet::SetAllocatedMessage(int number, FieldType type,
if (arena_ == NULL) {
delete extension->message_value;
}
- if (message->GetArena() == arena_) {
+ if (message_arena == arena_) {
extension->message_value = message;
+ } else if (message_arena == NULL) {
+ extension->message_value = message;
+ arena_->Own(message); // not NULL because not equal to message_arena
} else {
extension->message_value = message->New(arena_);
extension->message_value->CheckTypeAndMergeFrom(*message);
- if (message->GetArena() == NULL) {
- delete message;
- }
}
}
}
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index 09681259..bca179be 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -724,8 +724,7 @@ class RepeatedPrimitiveTypeTraits {
static const RepeatedFieldType* GetDefaultRepeatedField();
};
-LIBPROTOBUF_EXPORT extern ProtobufOnceType
-repeated_primitive_generic_type_traits_once_init_;
+LIBPROTOBUF_EXPORT extern ProtobufOnceType repeated_primitive_generic_type_traits_once_init_;
class LIBPROTOBUF_EXPORT RepeatedPrimitiveGenericTypeTraits {
private:
@@ -766,7 +765,7 @@ template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Add( \
} \
template<> inline const RepeatedField<TYPE>* \
RepeatedPrimitiveTypeTraits<TYPE>::GetDefaultRepeatedField() { \
- GoogleOnceInit( \
+ ::google::protobuf::GoogleOnceInit( \
&repeated_primitive_generic_type_traits_once_init_, \
&RepeatedPrimitiveGenericTypeTraits::InitializeDefaultRepeatedFields); \
return RepeatedPrimitiveGenericTypeTraits:: \
@@ -822,8 +821,7 @@ class LIBPROTOBUF_EXPORT StringTypeTraits {
}
};
-LIBPROTOBUF_EXPORT extern ProtobufOnceType
-repeated_string_type_traits_once_init_;
+LIBPROTOBUF_EXPORT extern ProtobufOnceType repeated_string_type_traits_once_init_;
class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
public:
@@ -868,7 +866,7 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
}
static const RepeatedFieldType* GetDefaultRepeatedField() {
- GoogleOnceInit(&repeated_string_type_traits_once_init_,
+ ::google::protobuf::GoogleOnceInit(&repeated_string_type_traits_once_init_,
&InitializeDefaultRepeatedFields);
return default_repeated_field_;
}
@@ -1034,8 +1032,7 @@ class RepeatedMessageTypeTraits {
static const RepeatedFieldType* GetDefaultRepeatedField();
};
-LIBPROTOBUF_EXPORT extern ProtobufOnceType
-repeated_message_generic_type_traits_once_init_;
+LIBPROTOBUF_EXPORT extern ProtobufOnceType repeated_message_generic_type_traits_once_init_;
// This class exists only to hold a generic default empty repeated field for all
// message-type repeated field extensions.
@@ -1052,7 +1049,7 @@ class LIBPROTOBUF_EXPORT RepeatedMessageGenericTypeTraits {
template<typename Type> inline
const typename RepeatedMessageTypeTraits<Type>::RepeatedFieldType*
RepeatedMessageTypeTraits<Type>::GetDefaultRepeatedField() {
- GoogleOnceInit(
+ ::google::protobuf::GoogleOnceInit(
&repeated_message_generic_type_traits_once_init_,
&RepeatedMessageGenericTypeTraits::InitializeDefaultRepeatedFields);
return reinterpret_cast<const RepeatedFieldType*>(
diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc
index 1569120d..f40fcbc2 100644
--- a/src/google/protobuf/extension_set_unittest.cc
+++ b/src/google/protobuf/extension_set_unittest.cc
@@ -360,9 +360,8 @@ TEST(ExtensionSetTest, ArenaSetAllocatedMessageAndRelease) {
unittest::ForeignMessage* foreign_message = new unittest::ForeignMessage();
message->SetAllocatedExtension(unittest::optional_foreign_message_extension,
foreign_message);
- // foreign_message is copied underneath, as foreign_message is on heap
- // and extension_set is on an arena.
- EXPECT_NE(foreign_message,
+ // foreign_message is now owned by the arena.
+ EXPECT_EQ(foreign_message,
message->MutableExtension(
unittest::optional_foreign_message_extension));
diff --git a/src/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc
index df043844..85ebdef1 100644
--- a/src/google/protobuf/generated_message_reflection_unittest.cc
+++ b/src/google/protobuf/generated_message_reflection_unittest.cc
@@ -43,6 +43,11 @@
// rather than generated accessors.
#include <google/protobuf/generated_message_reflection.h>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
#include <google/protobuf/descriptor.h>
#include <google/protobuf/test_util.h>
#include <google/protobuf/unittest.pb.h>
@@ -354,7 +359,7 @@ TEST(GeneratedMessageReflectionTest, ReleaseLast) {
ASSERT_EQ(2, message.repeated_foreign_message_size());
const protobuf_unittest::ForeignMessage* expected =
message.mutable_repeated_foreign_message(1);
- scoped_ptr<Message> released(message.GetReflection()->ReleaseLast(
+ google::protobuf::scoped_ptr<Message> released(message.GetReflection()->ReleaseLast(
&message, descriptor->FindFieldByName("repeated_foreign_message")));
EXPECT_EQ(expected, released.get());
}
@@ -377,9 +382,9 @@ TEST(GeneratedMessageReflectionTest, ReleaseLastExtensions) {
unittest::repeated_foreign_message_extension));
const protobuf_unittest::ForeignMessage* expected = message.MutableExtension(
unittest::repeated_foreign_message_extension, 1);
- scoped_ptr<Message> released(message.GetReflection()->ReleaseLast(
+ google::protobuf::scoped_ptr<Message> released(message.GetReflection()->ReleaseLast(
&message, descriptor->file()->FindExtensionByName(
- "repeated_foreign_message_extension")));
+ "repeated_foreign_message_extension")));
EXPECT_EQ(expected, released.get());
}
diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc
index afaca2ee..7b813f8a 100644
--- a/src/google/protobuf/generated_message_util.cc
+++ b/src/google/protobuf/generated_message_util.cc
@@ -63,7 +63,6 @@ void InitEmptyString() {
int StringSpaceUsedExcludingSelf(const string& str) {
const void* start = &str;
const void* end = &str + 1;
-
if (start <= str.data() && str.data() < end) {
// The string's data is stored inside the string object itself.
return 0;
@@ -73,6 +72,7 @@ int StringSpaceUsedExcludingSelf(const string& str) {
}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
index 630c9086..d1782e39 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -34,6 +34,10 @@
//
// This file contains tests and benchmarks.
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <vector>
#include <google/protobuf/io/coded_stream.h>
@@ -679,7 +683,7 @@ TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnStack) {
}
TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnHeap) {
- scoped_array<uint8> buffer(new uint8[8]);
+ google::protobuf::scoped_array<uint8> buffer(new uint8[8]);
CodedInputStream coded_input(buffer.get(), 8);
string str;
EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30));
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 9cdf0378..a598ef2e 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
@@ -44,6 +44,10 @@
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <string>
#include <iosfwd>
#include <google/protobuf/io/zero_copy_stream.h>
@@ -235,7 +239,7 @@ class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream
// Data is read into this buffer. It may be NULL if no buffer is currently
// in use. Otherwise, it points to an array of size buffer_size_.
- scoped_array<uint8> buffer_;
+ google::protobuf::scoped_array<uint8> buffer_;
const int buffer_size_;
// Number of valid bytes currently in the buffer (i.e. the size last
@@ -324,7 +328,7 @@ class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStrea
// Data is written from this buffer. It may be NULL if no buffer is
// currently in use. Otherwise, it points to an array of size buffer_size_.
- scoped_array<uint8> buffer_;
+ google::protobuf::scoped_array<uint8> buffer_;
const int buffer_size_;
// Number of valid bytes currently in the buffer (i.e. the size last
diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc
index 3850e76c..8c7358c1 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -57,6 +57,10 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <sstream>
#include <google/protobuf/io/zero_copy_stream_impl.h>
@@ -197,7 +201,7 @@ void IoTest::WriteString(ZeroCopyOutputStream* output, const string& str) {
}
void IoTest::ReadString(ZeroCopyInputStream* input, const string& str) {
- scoped_array<char> buffer(new char[str.size() + 1]);
+ google::protobuf::scoped_array<char> buffer(new char[str.size() + 1]);
buffer[str.size()] = '\0';
EXPECT_EQ(ReadFromInput(input, buffer.get(), str.size()), str.size());
EXPECT_STREQ(str.c_str(), buffer.get());
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index 8b61573d..52fba603 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -155,7 +155,7 @@ class LIBPROTOBUF_EXPORT MapKey {
"MapKey::GetUInt32Value");
return val_.uint32_value_;
}
- int32 GetBoolValue() const {
+ bool GetBoolValue() const {
TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL,
"MapKey::GetBoolValue");
return val_.bool_value_;
@@ -190,6 +190,8 @@ class LIBPROTOBUF_EXPORT MapKey {
GOOGLE_LOG(FATAL) << "Can't get here.";
return false;
}
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return false;
}
void CopyFrom(const MapKey& other) {
@@ -273,7 +275,7 @@ class LIBPROTOBUF_EXPORT MapValueRef {
"MapValueRef::SetInt32Value");
*reinterpret_cast<int32*>(data_) = value;
}
- void SetUInt32Value(uint64 value) {
+ void SetUInt32Value(uint32 value) {
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
"MapValueRef::SetUInt32Value");
*reinterpret_cast<uint32*>(data_) = value;
@@ -852,6 +854,8 @@ struct hash<google::protobuf::MapKey> {
GOOGLE_LOG(FATAL) << "Can't get here.";
return 0;
}
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return 0;
}
bool
operator()(const google::protobuf::MapKey& map_key1,
@@ -875,6 +879,8 @@ struct hash<google::protobuf::MapKey> {
GOOGLE_LOG(FATAL) << "Can't get here.";
return true;
}
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return true;
}
};
GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h
index 16c4a08f..f116697c 100644
--- a/src/google/protobuf/map_field_inl.h
+++ b/src/google/protobuf/map_field_inl.h
@@ -155,7 +155,8 @@ void TypeDefinedMapFieldBase<Key, T>::CopyIterator(
this_iter->key_.SetType(that_iter.key_.type());
// MapValueRef::type() fails when containing data is null. However, if
// this_iter points to MapEnd, data can be null.
- this_iter->value_.SetType((FieldDescriptor::CppType)that_iter.value_.type_);
+ this_iter->value_.SetType(
+ static_cast<FieldDescriptor::CppType>(that_iter.value_.type_));
SetMapIteratorValue(this_iter);
}
diff --git a/src/google/protobuf/map_proto2_unittest.proto b/src/google/protobuf/map_proto2_unittest.proto
index 6f9d6165..916cc546 100644
--- a/src/google/protobuf/map_proto2_unittest.proto
+++ b/src/google/protobuf/map_proto2_unittest.proto
@@ -31,6 +31,8 @@
syntax = "proto2";
+import "google/protobuf/unittest_import.proto";
+
// We don't put this in a package within proto2 because we need to make sure
// that the generated code doesn't depend on being in the proto2 namespace.
// In map_test_util.h we do "using namespace unittest = protobuf_unittest".
@@ -58,3 +60,7 @@ message TestEnumMapPlusExtra {
map<int32, Proto2MapEnumPlusExtra> known_map_field = 101;
map<int32, Proto2MapEnumPlusExtra> unknown_map_field = 102;
}
+
+message TestImportEnumMap {
+ map<int32, protobuf_unittest_import.ImportEnumForMap> import_enum_amp = 1;
+}
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index 16a24c25..451b02e8 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -2154,7 +2154,7 @@ TEST_F(MapFieldInDynamicMessageTest, MapIndependentOffsets) {
// Check that all fields have independent offsets by setting each
// 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> message(map_prototype_->New());
+ google::protobuf::scoped_ptr<Message> message(map_prototype_->New());
MapReflectionTester reflection_tester(map_descriptor_);
reflection_tester.SetMapFieldsViaReflection(message.get());
@@ -2163,7 +2163,7 @@ TEST_F(MapFieldInDynamicMessageTest, MapIndependentOffsets) {
TEST_F(MapFieldInDynamicMessageTest, DynamicMapReflection) {
// Check that map fields work properly.
- scoped_ptr<Message> message(map_prototype_->New());
+ google::protobuf::scoped_ptr<Message> message(map_prototype_->New());
// Check set functions.
MapReflectionTester reflection_tester(map_descriptor_);
@@ -2177,7 +2177,7 @@ TEST_F(MapFieldInDynamicMessageTest, MapSpaceUsed) {
// Since we share the implementation with generated messages, we don't need
// to test very much here. Just make sure it appears to be working.
- scoped_ptr<Message> message(map_prototype_->New());
+ google::protobuf::scoped_ptr<Message> message(map_prototype_->New());
MapReflectionTester reflection_tester(map_descriptor_);
int initial_space_used = message->SpaceUsed();
diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h
index 5040e605..f8ad7584 100644
--- a/src/google/protobuf/map_type_handler.h
+++ b/src/google/protobuf/map_type_handler.h
@@ -272,24 +272,24 @@ MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::ByteSize(
return WireFormatLite::MessageSizeNoVirtual(value);
}
-#define BYTE_SIZE(FieldType, DeclaredType) \
+#define GOOGLE_PROTOBUF_BYTE_SIZE(FieldType, DeclaredType) \
template <typename Type> \
inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
const MapEntryAccessorType& value) { \
return WireFormatLite::DeclaredType##Size(value); \
}
-BYTE_SIZE(STRING, String)
-BYTE_SIZE(BYTES , Bytes)
-BYTE_SIZE(INT64 , Int64)
-BYTE_SIZE(UINT64, UInt64)
-BYTE_SIZE(INT32 , Int32)
-BYTE_SIZE(UINT32, UInt32)
-BYTE_SIZE(SINT64, SInt64)
-BYTE_SIZE(SINT32, SInt32)
-BYTE_SIZE(ENUM , Enum)
-
-#undef BYTE_SIZE
+GOOGLE_PROTOBUF_BYTE_SIZE(STRING, String)
+GOOGLE_PROTOBUF_BYTE_SIZE(BYTES , Bytes)
+GOOGLE_PROTOBUF_BYTE_SIZE(INT64 , Int64)
+GOOGLE_PROTOBUF_BYTE_SIZE(UINT64, UInt64)
+GOOGLE_PROTOBUF_BYTE_SIZE(INT32 , Int32)
+GOOGLE_PROTOBUF_BYTE_SIZE(UINT32, UInt32)
+GOOGLE_PROTOBUF_BYTE_SIZE(SINT64, SInt64)
+GOOGLE_PROTOBUF_BYTE_SIZE(SINT32, SInt32)
+GOOGLE_PROTOBUF_BYTE_SIZE(ENUM , Enum)
+
+#undef GOOGLE_PROTOBUF_BYTE_SIZE
#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \
template <typename Type> \
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index 2f6416d0..032748bd 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -55,7 +55,6 @@
#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/singleton.h>
#include <google/protobuf/stubs/stl_util.h>
-#include <google/protobuf/stubs/port.h>
namespace google {
namespace protobuf {
@@ -495,11 +494,19 @@ Message* GenericTypeHandler<Message>::NewFromPrototype(
return prototype->New(arena);
}
template<>
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+// Note: force noinline to workaround MSVC 2015 compiler bug, issue #240
+GOOGLE_ATTRIBUTE_NOINLINE
+#endif
google::protobuf::Arena* GenericTypeHandler<Message>::GetArena(
Message* value) {
return value->GetArena();
}
template<>
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+// Note: force noinline to workaround MSVC 2015 compiler bug, issue #240
+GOOGLE_ATTRIBUTE_NOINLINE
+#endif
void* GenericTypeHandler<Message>::GetMaybeArenaPointer(
Message* value) {
return value->GetMaybeArenaPointer();
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index 348e7c7f..7c27afd9 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -971,7 +971,7 @@ class LIBPROTOBUF_EXPORT Reflection {
return false;
}
- // Returns a MaIterator referring to the first element in the map field.
+ // Returns a MapIterator 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(
diff --git a/src/google/protobuf/metadata.h b/src/google/protobuf/metadata.h
index fdee150b..219645d3 100644
--- a/src/google/protobuf/metadata.h
+++ b/src/google/protobuf/metadata.h
@@ -56,7 +56,7 @@ namespace internal {
// The tagged pointer uses the LSB to disambiguate cases, and uses bit 0 == 0 to
// indicate an arena pointer and bit 0 == 1 to indicate a UFS+Arena-container
// pointer.
-class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
+class InternalMetadataWithArena {
public:
InternalMetadataWithArena() : ptr_(NULL) {}
explicit InternalMetadataWithArena(Arena* arena)
diff --git a/src/google/protobuf/proto_cast.h b/src/google/protobuf/proto_cast.h
deleted file mode 100644
index dc0e9aca..00000000
--- a/src/google/protobuf/proto_cast.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef GOOGLE_PROTOBUF_UTIL_PROTO_CAST_H__
-#define GOOGLE_PROTOBUF_UTIL_PROTO_CAST_H__
-
-#include <string>
-
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-
-// proto_cast<> is used to simulate over-the-wire conversion of one
-// proto message into another. This is primarily useful for unit tests
-// which validate the version-compatibility semantics of protobufs.
-// Usage is similar to C++-style typecasts:
-//
-// OldMessage old_message = /*...*/;
-// NewMessage new_message = proto_cast<NewMessage>(old_message);
-namespace google {
-template<typename NewProto,
- typename OldProto>
-NewProto proto_cast(const OldProto& old_proto) {
- string wire_format;
- GOOGLE_CHECK(old_proto.SerializeToString(&wire_format));
-
- NewProto new_proto;
- GOOGLE_CHECK(new_proto.ParseFromString(wire_format));
- return new_proto;
-}
-
-} // namespace google
-#endif // GOOGLE_PROTOBUF_UTIL_PROTO_CAST_H__
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index b10e7a95..5530fefe 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -649,7 +649,7 @@ inline const Message& GenericTypeHandler<Message>::default_instance() {
// StringTypeHandler is exported. So, we factor out StringTypeHandlerBase,
// export that, then make StringTypeHandler be a subclass which is NOT
// exported.
-// TODO(kenton): Now that StringSpaceUsedExcludingSelf() is in the lite
+// TODO(kenton): Now that StringSpaceUsedExcludingSelf() is in the lite
// library, this can be cleaned up.
class LIBPROTOBUF_EXPORT StringTypeHandlerBase {
public:
diff --git a/src/google/protobuf/stubs/callback.h b/src/google/protobuf/stubs/callback.h
index c4f9edee..6da530d3 100644
--- a/src/google/protobuf/stubs/callback.h
+++ b/src/google/protobuf/stubs/callback.h
@@ -325,8 +325,6 @@ class MethodResultCallback_5_2 : public ResultCallback2<R, A1, A2> {
typename remove_reference<P5>::type p5_;
};
-} // namespace internal
-
// See Closure.
inline Closure* NewCallback(void (*function)()) {
return new internal::FunctionClosure0(function, true);
@@ -452,6 +450,8 @@ inline ResultCallback2<R, A1, A2>* NewPermanentCallback(
p2, p3, p4, p5);
}
+} // namespace internal
+
// A function which does nothing. Useful for creating no-op callbacks, e.g.:
// Closure* nothing = NewCallback(&DoNothing);
void LIBPROTOBUF_EXPORT DoNothing();
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index 88e7084f..9c05cac3 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -146,7 +146,7 @@ namespace internal {
LIBPROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len);
inline bool IsStructurallyValidUTF8(const std::string& str) {
- return IsStructurallyValidUTF8(str.data(), str.length());
+ return IsStructurallyValidUTF8(str.data(), static_cast<int>(str.length()));
}
// Returns initial number of bytes of structually valid UTF-8.
diff --git a/src/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc
index f9e2cfd4..25bae9b0 100644
--- a/src/google/protobuf/stubs/common_unittest.cc
+++ b/src/google/protobuf/stubs/common_unittest.cc
@@ -41,6 +41,8 @@
namespace google {
namespace protobuf {
+using internal::NewCallback;
+using internal::NewPermanentCallback;
namespace {
// TODO(kenton): More tests.
diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h
index c6f210f0..58334322 100755
--- a/src/google/protobuf/stubs/hash.h
+++ b/src/google/protobuf/stubs/hash.h
@@ -41,10 +41,15 @@
#define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1
#define GOOGLE_PROTOBUF_HAVE_HASH_SET 1
-// Use C++11 unordered_{map|set} if available. Otherwise, libc++ always support
-// unordered_{map|set}
-#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X) || \
- defined(_LIBCPP_VERSION)
+// Android
+#if defined(__ANDROID__)
+# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP
+# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP
+
+// Use C++11 unordered_{map|set} if available.
+#elif ((_LIBCPP_STD_VER >= 11) || \
+ (((__cplusplus >= 201103L) || defined(__GXX_EXPERIMENTAL_CXX0X)) && \
+ (__GLIBCXX__ > 20090421)))
# define GOOGLE_PROTOBUF_HAS_CXX11_HASH
// For XCode >= 4.6: the compiler is clang with libc++.
diff --git a/src/google/protobuf/stubs/int128.cc b/src/google/protobuf/stubs/int128.cc
index 9f4fb824..d80c64f2 100644
--- a/src/google/protobuf/stubs/int128.cc
+++ b/src/google/protobuf/stubs/int128.cc
@@ -188,7 +188,8 @@ std::ostream& operator<<(std::ostream& o, const uint128& b) {
if ((flags & std::ios::adjustfield) == std::ios::left) {
rep.append(width - rep.size(), o.fill());
} else {
- rep.insert(0, width - rep.size(), o.fill());
+ rep.insert(static_cast<std::string::size_type>(0),
+ width - rep.size(), o.fill());
}
}
diff --git a/src/google/protobuf/stubs/once_unittest.cc b/src/google/protobuf/stubs/once_unittest.cc
index cb5a20dd..37def58d 100644
--- a/src/google/protobuf/stubs/once_unittest.cc
+++ b/src/google/protobuf/stubs/once_unittest.cc
@@ -43,6 +43,7 @@
namespace google {
namespace protobuf {
+using internal::NewCallback;
namespace {
class OnceInitTest : public testing::Test {
@@ -127,10 +128,11 @@ class OnceInitTest : public testing::Test {
};
TestThread* RunInitOnceInNewThread() {
- return new TestThread(NewCallback(this, &OnceInitTest::InitOnce));
+ return new TestThread(internal::NewCallback(this, &OnceInitTest::InitOnce));
}
TestThread* RunInitRecursiveOnceInNewThread() {
- return new TestThread(NewCallback(this, &OnceInitTest::InitRecursiveOnce));
+ return new TestThread(
+ internal::NewCallback(this, &OnceInitTest::InitRecursiveOnce));
}
enum State {
diff --git a/src/google/protobuf/stubs/stringpiece.h b/src/google/protobuf/stubs/stringpiece.h
index 353a60d3..ec3ffd5b 100644
--- a/src/google/protobuf/stubs/stringpiece.h
+++ b/src/google/protobuf/stubs/stringpiece.h
@@ -149,6 +149,7 @@
#include <string>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/hash.h>
namespace google {
namespace protobuf {
@@ -437,4 +438,16 @@ extern std::ostream& operator<<(std::ostream& o, StringPiece piece);
} // namespace protobuf
} // namespace google
+GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START
+template<> struct hash<StringPiece> {
+ size_t operator()(const StringPiece& s) const {
+ size_t result = 0;
+ for (const char *str = s.data(), *end = str + s.size(); str < end; str++) {
+ result = 5 * result + *str;
+ }
+ return result;
+ }
+};
+GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
+
#endif // STRINGS_STRINGPIECE_H_
diff --git a/src/google/protobuf/stubs/stringpiece_unittest.cc b/src/google/protobuf/stubs/stringpiece_unittest.cc
index 9b5dae13..43737a57 100644
--- a/src/google/protobuf/stubs/stringpiece_unittest.cc
+++ b/src/google/protobuf/stubs/stringpiece_unittest.cc
@@ -36,6 +36,7 @@
#include <vector>
#include <google/protobuf/testing/googletest.h>
+#include <google/protobuf/stubs/hash.h>
#include <gtest/gtest.h>
namespace google {
@@ -745,6 +746,23 @@ TEST(StringPiece, Comparisons2) {
EXPECT_TRUE(abc.ends_with("nopqrstuvwxyz"));
}
+TEST(StringPiece, HashFunction) {
+ hash_set<StringPiece> set;
+
+ set.insert(StringPiece("hello"));
+ EXPECT_EQ(1, set.size());
+
+ // Insert a StringPiece of the same value again and should NOT increment
+ // size of the set.
+ set.insert(StringPiece("hello"));
+ EXPECT_EQ(1, set.size());
+
+ // Insert a StringPiece with different value and check that size of the set
+ // has been increment by one.
+ set.insert(StringPiece("world"));
+ EXPECT_EQ(2, set.size());
+}
+
TEST(ComparisonOpsTest, StringCompareNotAmbiguous) {
EXPECT_EQ("hello", string("hello"));
EXPECT_LT("hello", string("world"));
diff --git a/src/google/protobuf/testing/googletest.cc b/src/google/protobuf/testing/googletest.cc
index b8bd790b..2b9cddef 100644
--- a/src/google/protobuf/testing/googletest.cc
+++ b/src/google/protobuf/testing/googletest.cc
@@ -94,6 +94,13 @@ string TestSourceDir() {
namespace {
string GetTemporaryDirectoryName() {
+ // Tests run under Bazel "should not" use /tmp. Bazel sets this environment
+ // variable for tests to use instead.
+ char *from_environment = getenv("TEST_TMPDIR");
+ if (from_environment != NULL && from_environment[0] != '\0') {
+ return string(from_environment) + "/protobuf_tmpdir";
+ }
+
// tmpnam() is generally not considered safe but we're only using it for
// testing. We cannot use tmpfile() or mkstemp() since we're creating a
// directory.
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index 4d8c1f91..38b9069b 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -377,8 +377,8 @@ class TextFormat::Parser::ParserImpl {
if (internal::GetAnyFieldDescriptors(*message, &any_type_url_field,
&any_value_field) &&
TryConsume("[")) {
- string full_type_name;
- DO(ConsumeAnyTypeUrl(&full_type_name));
+ string full_type_name, prefix;
+ DO(ConsumeAnyTypeUrl(&full_type_name, &prefix));
DO(Consume("]"));
string serialized_value;
DO(ConsumeAnyValue(full_type_name,
@@ -386,7 +386,7 @@ class TextFormat::Parser::ParserImpl {
&serialized_value));
reflection->SetString(
message, any_type_url_field,
- string(internal::kTypeGoogleApisComPrefix) + full_type_name);
+ string(prefix + full_type_name));
reflection->SetString(message, any_value_field, serialized_value);
return true;
// Fall through.
@@ -981,7 +981,8 @@ class TextFormat::Parser::ParserImpl {
}
// Consumes Any::type_url value, of form "type.googleapis.com/full.type.Name"
- bool ConsumeAnyTypeUrl(string* full_type_name) {
+ // or "type.googleprod.com/full.type.Name"
+ bool ConsumeAnyTypeUrl(string* full_type_name, string* prefix) {
// TODO(saito) Extend Consume() to consume multiple tokens at once, so that
// this code can be written as just DO(Consume(kGoogleApisTypePrefix)).
string url1, url2, url3;
@@ -993,10 +994,12 @@ class TextFormat::Parser::ParserImpl {
DO(Consume("/"));
DO(ConsumeFullTypeName(full_type_name));
- const string prefix = url1 + "." + url2 + "." + url3 + "/";
- if (prefix != internal::kTypeGoogleApisComPrefix) {
+ *prefix = url1 + "." + url2 + "." + url3 + "/";
+ if (*prefix != internal::kTypeGoogleApisComPrefix &&
+ *prefix != internal::kTypeGoogleProdComPrefix) {
ReportError("TextFormat::Parser for Any supports only "
- "type.googleapi.com, but found \"" + prefix + "\"");
+ "type.googleapis.com and type.googleprod.com, "
+ "but found \"" + *prefix + "\"");
return false;
}
return true;
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index 1aafd8e6..8d61be19 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -37,6 +37,10 @@
#include <math.h>
#include <stdlib.h>
#include <limits>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
@@ -931,7 +935,7 @@ class TextFormatParserTest : public testing::Test {
protected:
void ExpectFailure(const string& input, const string& message, int line,
int col) {
- scoped_ptr<unittest::TestAllTypes> proto(new unittest::TestAllTypes);
+ google::protobuf::scoped_ptr<unittest::TestAllTypes> proto(new unittest::TestAllTypes);
ExpectFailure(input, message, line, col, proto.get());
}
@@ -992,7 +996,7 @@ class TextFormatParserTest : public testing::Test {
};
TEST_F(TextFormatParserTest, ParseInfoTreeBuilding) {
- scoped_ptr<unittest::TestAllTypes> message(new unittest::TestAllTypes);
+ google::protobuf::scoped_ptr<unittest::TestAllTypes> message(new unittest::TestAllTypes);
const Descriptor* d = message->GetDescriptor();
string stringData =
@@ -1057,7 +1061,7 @@ TEST_F(TextFormatParserTest, ParseInfoTreeBuilding) {
}
TEST_F(TextFormatParserTest, ParseFieldValueFromString) {
- scoped_ptr<unittest::TestAllTypes> message(new unittest::TestAllTypes);
+ google::protobuf::scoped_ptr<unittest::TestAllTypes> message(new unittest::TestAllTypes);
const Descriptor* d = message->GetDescriptor();
#define EXPECT_FIELD(name, value, valuestring) \
diff --git a/src/google/protobuf/unittest_import.proto b/src/google/protobuf/unittest_import.proto
index 7e165220..8d03e388 100644
--- a/src/google/protobuf/unittest_import.proto
+++ b/src/google/protobuf/unittest_import.proto
@@ -64,3 +64,10 @@ enum ImportEnum {
IMPORT_BAZ = 9;
}
+
+// To use an enum in a map, it must has the first value as 0.
+enum ImportEnumForMap {
+ UNKNOWN = 0;
+ FOO = 1;
+ BAR = 2;
+}
diff --git a/src/google/protobuf/unknown_enum_impl.h b/src/google/protobuf/unknown_enum_impl.h
deleted file mode 100644
index 7c68ad6c..00000000
--- a/src/google/protobuf/unknown_enum_impl.h
+++ /dev/null
@@ -1,154 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef GOOGLE_PROTOBUF_UTIL_UNKNOWN_ENUM_IMPL_H__
-#define GOOGLE_PROTOBUF_UTIL_UNKNOWN_ENUM_IMPL_H__
-
-#include <stdlib.h>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/bridge/compatibility_mode_support.h>
-
-namespace google {
-namespace protobuf {
-
-// google/protobuf/message.h
-class Message;
-
-namespace util {
-
-// NOTE: You should not call these functions directly. Instead use either
-// HAS_UNKNOWN_ENUM() or GET_UNKNOWN_ENUM(), defined in the public header.
-// The macro-versions operate in a type-safe manner and behave appropriately
-// for the proto version of the message, whereas these versions assume a
-// specific proto version and allow the caller to pass in any arbitrary integer
-// value as a field number.
-//
-// Returns whether the message has unrecognized the enum value for a given
-// field. It also stores the value into the unknown_value parameter if the
-// function returns true and the pointer is not NULL.
-//
-// 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 = NULL);
-// Same as above, but returns all unknown enums.
-bool GetRepeatedEnumUnknowns(const Message& message, int32 field_number,
- vector<int32>* 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.
-bool HasUnknownEnumProto1(const Message& message, int32 field_number,
- int32* unknown_value);
-// Same as above, but returns all unknown enums.
-bool GetRepeatedEnumUnknownsProto1(const Message& message, int32 field_number,
- vector<int32>* unknown_values);
-// Invokes the appropriate version based on whether the message is proto1
-// or proto2.
-template <typename T>
-bool HasUnknownEnum_Template(const T& message, int32 field_number,
- int32* unknown_value = NULL) {
- if (internal::is_base_of<bridge::internal::Proto1CompatibleMessage, T>::value ||
- !internal::is_base_of<ProtocolMessage, T>::value) {
- return HasUnknownEnum(message, field_number, unknown_value);
- } else {
- return HasUnknownEnumProto1(message, field_number, unknown_value);
- }
-}
-// Invokes the appropriate version based on whether the message is proto1
-// or proto2.
-template <typename T>
-bool GetRepeatedEnumUnknowns_Template(
- const T& message, int32 field_number,
- vector<int32>* unknown_values = NULL) {
- if (internal::is_base_of<bridge::internal::Proto1CompatibleMessage, T>::value ||
- !internal::is_base_of<ProtocolMessage, T>::value) {
- return GetRepeatedEnumUnknowns(message, field_number, unknown_values);
- } else {
- return GetRepeatedEnumUnknownsProto1(message, field_number,
- unknown_values);
- }
-}
-
-// NOTE: You should not call these functions directly. Instead use
-// CLEAR_UNKNOWN_ENUM(), defined in the public header. The macro-versions
-// operate in a type-safe manner and behave appropriately for the proto
-// version of the message, whereas these versions assume a specific proto
-// version and allow the caller to pass in any arbitrary integer value as a
-// field number.
-//
-// Clears the unknown entries of the given field of the message.
-void ClearUnknownEnum(Message* message, int32 field_number);
-// In proto1, clears the field if the value is out of range.
-// TODO(karner): Delete this or make it proto2-only once the migration
-// to proto2 is complete.
-void ClearUnknownEnumProto1(Message* message, int32 field_number);
-template <typename T>
-void ClearUnknownEnum_Template(T* message, int32 field_number) {
- if (internal::is_base_of<bridge::internal::Proto1CompatibleMessage, T>::value ||
- !internal::is_base_of<ProtocolMessage, T>::value) {
- ClearUnknownEnum(message, field_number);
- } else {
- ClearUnknownEnumProto1(message, field_number);
- }
-}
-
-// NOTE: You should not call these functions directly. Instead use
-// SET_UNKNOWN_ENUM(), defined in the public header. The macro-versions
-// operate in a type-safe manner and behave appropriately for the proto
-// version of the message, whereas these versions assume a specific proto
-// version and allow the caller to pass in any arbitrary integer value as a
-// field number.
-//
-// Sets the given value in the unknown fields of the message.
-void SetUnknownEnum(Message* message, int32 field_number, int32 unknown_value);
-// 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.
-void SetUnknownEnumProto1(Message* message, int32 field_number,
- int32 unknown_value);
-// Invokes the appropriate version based on whether the message is proto1
-// or proto2.
-template <typename T>
-void SetUnknownEnum_Template(T* message, int32 field_number,
- int32 unknown_value) {
- if (internal::is_base_of<bridge::internal::Proto1CompatibleMessage, T>::value ||
- !internal::is_base_of<ProtocolMessage, T>::value) {
- SetUnknownEnum(message, field_number, unknown_value);
- } else {
- SetUnknownEnumProto1(message, field_number, unknown_value);
- }
-}
-
-} // namespace util
-} // namespace protobuf
-
-} // namespace google
-#endif // GOOGLE_PROTOBUF_UTIL_UNKNOWN_ENUM_IMPL_H__
diff --git a/src/google/protobuf/unknown_enum_test.proto b/src/google/protobuf/unknown_enum_test.proto
deleted file mode 100644
index 3c549cc7..00000000
--- a/src/google/protobuf/unknown_enum_test.proto
+++ /dev/null
@@ -1,62 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Definitions of protos for testing cross-version compatibility. The
-// UpRevision message acts as if it were a newer version of the DownRevision
-// message. That is, UpRevision shares all the same fields as DownRevision,
-// but UpRevision can add fields and add enum values.
-syntax = "proto2";
-
-package google.protobuf.util;
-
-option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
-
-message DownRevision {
- enum Enum {
- DEFAULT_VALUE = 2;
- NONDEFAULT_VALUE = 3;
- }
-
- optional Enum value = 1 [default = DEFAULT_VALUE];
- repeated Enum values = 2;
-}
-
-message UpRevision {
- enum Enum {
- DEFAULT_VALUE = 2;
- NONDEFAULT_VALUE = 3;
- NEW_VALUE = 4;
- NEW_VALUE_2 = 5;
- NEW_VALUE_3 = 6;
- }
-
- optional Enum value = 1 [default = DEFAULT_VALUE];
- repeated Enum values = 2;
-}
diff --git a/src/google/protobuf/util/field_comparator_test.cc b/src/google/protobuf/util/field_comparator_test.cc
index 845839ac..748c7d11 100644
--- a/src/google/protobuf/util/field_comparator_test.cc
+++ b/src/google/protobuf/util/field_comparator_test.cc
@@ -34,8 +34,8 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/descriptor.h>
-#include <google/protobuf/stubs/mathutil.h>
#include <gtest/gtest.h>
+#include <google/protobuf/stubs/mathutil.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/util/field_mask_util.cc b/src/google/protobuf/util/field_mask_util.cc
index 82034bd4..29ca9c1e 100644
--- a/src/google/protobuf/util/field_mask_util.cc
+++ b/src/google/protobuf/util/field_mask_util.cc
@@ -43,7 +43,7 @@ string FieldMaskUtil::ToString(const FieldMask& mask) {
return Join(mask.paths(), ",");
}
-void FieldMaskUtil::FromString(const string& str, FieldMask* out) {
+void FieldMaskUtil::FromString(StringPiece str, FieldMask* out) {
out->Clear();
vector<string> paths = Split(str, ",");
for (int i = 0; i < paths.size(); ++i) {
@@ -53,7 +53,7 @@ void FieldMaskUtil::FromString(const string& str, FieldMask* out) {
}
bool FieldMaskUtil::InternalIsValidPath(const Descriptor* descriptor,
- const string& path) {
+ StringPiece path) {
vector<string> parts = Split(path, ".");
for (int i = 0; i < parts.size(); ++i) {
const string& field_name = parts[i];
@@ -386,15 +386,15 @@ void FieldMaskUtil::Intersect(const FieldMask& mask1, const FieldMask& mask2,
intersection.MergeToFieldMask(out);
}
-bool FieldMaskUtil::IsPathInFieldMask(const string& path,
- const FieldMask& mask) {
+bool FieldMaskUtil::IsPathInFieldMask(StringPiece path, const FieldMask& mask) {
for (int i = 0; i < mask.paths_size(); ++i) {
const string& mask_path = mask.paths(i);
if (path == mask_path) {
return true;
} else if (mask_path.length() < path.length()) {
// Also check whether mask.paths(i) is a prefix of path.
- if (path.compare(0, mask_path.length() + 1, mask_path + ".") == 0) {
+ if (path.substr(0, mask_path.length() + 1).compare(mask_path + ".") ==
+ 0) {
return true;
}
}
diff --git a/src/google/protobuf/util/field_mask_util.h b/src/google/protobuf/util/field_mask_util.h
index c99c34f8..92f69893 100644
--- a/src/google/protobuf/util/field_mask_util.h
+++ b/src/google/protobuf/util/field_mask_util.h
@@ -35,6 +35,7 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/field_mask.pb.h>
+#include <google/protobuf/stubs/stringpiece.h>
namespace google {
namespace protobuf {
@@ -47,11 +48,11 @@ class LIBPROTOBUF_EXPORT FieldMaskUtil {
// Converts FieldMask to/from string, formatted according to proto3 JSON
// spec for FieldMask (e.g., "foo,bar,baz.quz").
static string ToString(const FieldMask& mask);
- static void FromString(const string& str, FieldMask* out);
+ static void FromString(StringPiece str, FieldMask* out);
// Checks whether the given path is valid for type T.
template <typename T>
- static bool IsValidPath(const string& path) {
+ static bool IsValidPath(StringPiece path) {
return InternalIsValidPath(T::descriptor(), path);
}
@@ -67,7 +68,7 @@ class LIBPROTOBUF_EXPORT FieldMaskUtil {
// Adds a path to FieldMask after checking whether the given path is valid.
// This method check-fails if the path is not a valid path for type T.
template <typename T>
- static void AddPathToFieldMask(const string& path, FieldMask* mask) {
+ static void AddPathToFieldMask(StringPiece path, FieldMask* mask) {
GOOGLE_CHECK(IsValidPath<T>(path));
mask->add_paths(path);
}
@@ -96,7 +97,7 @@ class LIBPROTOBUF_EXPORT FieldMaskUtil {
// Returns true if path is covered by the given FieldMask. Note that path
// "foo.bar" covers all paths like "foo.bar.baz", "foo.bar.quz.x", etc.
- static bool IsPathInFieldMask(const string& path, const FieldMask& mask);
+ static bool IsPathInFieldMask(StringPiece path, const FieldMask& mask);
class MergeOptions;
// Merges fields specified in a FieldMask into another message.
@@ -105,7 +106,7 @@ class LIBPROTOBUF_EXPORT FieldMaskUtil {
private:
static bool InternalIsValidPath(const Descriptor* descriptor,
- const string& path);
+ StringPiece path);
static void InternalGetFieldMaskForAllFields(const Descriptor* descriptor,
FieldMask* out);
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h
index d4547601..bcb526e8 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.h
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.h
@@ -110,7 +110,7 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// "Node" represents a node in the tree that holds the input of
// DefaultValueObjectWriter.
- class Node {
+ class LIBPROTOBUF_EXPORT Node {
public:
Node(const string& name, const google::protobuf::Type* type, NodeKind kind,
const DataPiece& data, bool is_placeholder);
diff --git a/src/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc
index f81e3306..94d2ab7a 100644
--- a/src/google/protobuf/util/internal/json_objectwriter.cc
+++ b/src/google/protobuf/util/internal/json_objectwriter.cc
@@ -37,8 +37,8 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/util/internal/utility.h>
#include <google/protobuf/util/internal/json_escaping.h>
-#include <google/protobuf/stubs/mathlimits.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/mathlimits.h>
namespace google {
namespace protobuf {
@@ -116,7 +116,7 @@ JsonObjectWriter* JsonObjectWriter::RenderUint64(StringPiece name,
JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name,
double value) {
- if (google::protobuf::MathLimits<double>::IsFinite(value)) {
+ if (MathLimits<double>::IsFinite(value)) {
return RenderSimple(name, SimpleDtoa(value));
}
@@ -126,7 +126,7 @@ JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name,
JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name,
float value) {
- if (google::protobuf::MathLimits<float>::IsFinite(value)) {
+ if (MathLimits<float>::IsFinite(value)) {
return RenderSimple(name, SimpleFtoa(value));
}
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc
index 996e1f8c..aebf19a1 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource.cc
@@ -47,7 +47,6 @@
#include <google/protobuf/util/internal/utility.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/once.h>
#include <google/protobuf/stubs/status_macros.h>
@@ -140,6 +139,7 @@ Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type,
const uint32 end_tag,
bool include_start_and_end,
ObjectWriter* ow) const {
+
const TypeRenderer* type_renderer = FindTypeRenderer(type.name());
if (type_renderer != NULL) {
return (*type_renderer)(this, type, name, ow);
@@ -332,10 +332,9 @@ Status ProtoStreamObjectSource::RenderDuration(
if (seconds < 0) {
if (nanos > 0) {
return Status(util::error::INTERNAL,
- StrCat(
- "Duration nanos is non-negative, but seconds is "
- "negative for field: ",
- field_name));
+ StrCat("Duration nanos is non-negative, but seconds is "
+ "negative for field: ",
+ field_name));
}
sign = "-";
seconds = -seconds;
@@ -648,6 +647,7 @@ Status ProtoStreamObjectSource::RenderFieldMask(
return Status::OK;
}
+
hash_map<string, ProtoStreamObjectSource::TypeRenderer>*
ProtoStreamObjectSource::renderers_ = NULL;
GOOGLE_PROTOBUF_DECLARE_ONCE(source_renderers_init_);
@@ -670,13 +670,16 @@ void ProtoStreamObjectSource::InitRendererMap() {
&ProtoStreamObjectSource::RenderInt32;
(*renderers_)["google.protobuf.UInt32Value"] =
&ProtoStreamObjectSource::RenderUInt32;
- (*renderers_)["google.protobuf.BoolValue"] = &ProtoStreamObjectSource::RenderBool;
+ (*renderers_)["google.protobuf.BoolValue"] =
+ &ProtoStreamObjectSource::RenderBool;
(*renderers_)["google.protobuf.StringValue"] =
&ProtoStreamObjectSource::RenderString;
(*renderers_)["google.protobuf.BytesValue"] =
&ProtoStreamObjectSource::RenderBytes;
- (*renderers_)["google.protobuf.Any"] = &ProtoStreamObjectSource::RenderAny;
- (*renderers_)["google.protobuf.Struct"] = &ProtoStreamObjectSource::RenderStruct;
+ (*renderers_)["google.protobuf.Any"] =
+ &ProtoStreamObjectSource::RenderAny;
+ (*renderers_)["google.protobuf.Struct"] =
+ &ProtoStreamObjectSource::RenderStruct;
(*renderers_)["google.protobuf.Value"] =
&ProtoStreamObjectSource::RenderStructValue;
(*renderers_)["google.protobuf.ListValue"] =
@@ -835,6 +838,7 @@ Status ProtoStreamObjectSource::RenderField(
StrCat("Invalid configuration. Could not find the type: ",
field->type_url()));
}
+
RETURN_IF_ERROR(WriteMessage(*type, field_name, 0, true, ow));
if (!stream_->ConsumedEntireMessage()) {
return Status(util::error::INVALID_ARGUMENT,
@@ -988,7 +992,7 @@ std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos(
uint32 nanos = 0;
uint32 tag = 0;
int64 signed_seconds = 0;
- int64 signed_nanos = 0;
+ int32 signed_nanos = 0;
for (tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) {
const google::protobuf::Field* field = FindAndVerifyField(type, tag);
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h
index f52383a1..3cd37aa1 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.h
+++ b/src/google/protobuf/util/internal/protostream_objectsource.h
@@ -188,8 +188,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
// Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter.
static util::Status RenderStructListValue(
- const ProtoStreamObjectSource* os,
- const google::protobuf::Type& type,
+ const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
StringPiece name, ObjectWriter* ow);
// Render the "Any" type.
@@ -211,6 +210,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
util::Status RenderField(const google::protobuf::Field* field,
StringPiece field_name, ObjectWriter* ow) const;
+
// Reads field value according to Field spec in 'field' and returns the read
// value as string. This only works for primitive datatypes (no message
// types).
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
index a935ac39..08a2fb9a 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -33,13 +33,13 @@
#include <functional>
#include <stack>
+#include <google/protobuf/stubs/once.h>
#include <google/protobuf/stubs/time.h>
#include <google/protobuf/wire_format_lite.h>
#include <google/protobuf/util/internal/field_mask_utility.h>
#include <google/protobuf/util/internal/object_location_tracker.h>
#include <google/protobuf/util/internal/constants.h>
#include <google/protobuf/util/internal/utility.h>
-#include <google/protobuf/stubs/once.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/statusor.h>
@@ -397,8 +397,8 @@ void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece(
const TypeRenderer* type_renderer =
FindTypeRenderer(GetFullTypeWithUrl(ow_->master_type_.name()));
if (type_renderer) {
- // TODO(rikka): Don't just ignore the util::Status object!
- (*type_renderer)(ow_.get(), value);
+ Status status = (*type_renderer)(ow_.get(), value);
+ if (!status.ok()) ow_->InvalidValue("Any", status.error_message());
} else {
ow_->RenderDataPiece(name, value);
}
@@ -600,6 +600,11 @@ void ProtoStreamObjectWriter::ProtoElement::TakeOneofIndex(int32 index) {
InsertIfNotPresent(&oneof_indices_, index);
}
+bool ProtoStreamObjectWriter::ProtoElement::InsertMapKeyIfNotPresent(
+ StringPiece map_key) {
+ return InsertIfNotPresent(&map_keys_, map_key);
+}
+
inline void ProtoStreamObjectWriter::InvalidName(StringPiece unknown_name,
StringPiece message) {
listener_->InvalidName(location(), ToSnakeCase(unknown_name), message);
@@ -643,6 +648,11 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject(
return this;
} else if (element_ != NULL &&
(element_->IsMap() || element_->IsStructMap())) {
+ if (!ValidMapKey(name)) {
+ ++invalid_depth_;
+ return this;
+ }
+
field = StartMapEntry(name);
if (element_->IsStructMapEntry()) {
// If the top element is a map entry, this means we are starting another
@@ -698,7 +708,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject(
element_.reset(
new ProtoElement(element_.release(), field, *type, ProtoElement::MAP));
} else {
- WriteTag(*field);
+ WriteTag(*field);
element_.reset(new ProtoElement(element_.release(), field, *type,
ProtoElement::MESSAGE));
}
@@ -863,6 +873,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndObject() {
// struct.
SkipElements();
+
// If ending the root element,
// then serialize the full message with calculated sizes.
if (element_ == NULL) {
@@ -914,6 +925,11 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) {
// Check if we need to start a map. This can heppen when there is either a map
// or a struct type within a list.
if (element_->IsMap() || element_->IsStructMap()) {
+ if (!ValidMapKey(name)) {
+ ++invalid_depth_;
+ return this;
+ }
+
field = StartMapEntry(name);
if (field == NULL) return this;
@@ -969,7 +985,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) {
ProtoElement::MESSAGE));
InvalidValue("Map", "Cannot bind a list to map.");
++invalid_depth_;
- element_->pop();
+ element_.reset(element_->pop());
return this;
}
@@ -1113,7 +1129,7 @@ Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow,
// conversions as much as possible. Because ToSnakeCase sometimes returns the
// wrong value.
google::protobuf::scoped_ptr<ResultCallback1<util::Status, StringPiece> > callback(
- NewPermanentCallback(&RenderOneFieldPath, ow));
+ google::protobuf::internal::NewPermanentCallback(&RenderOneFieldPath, ow));
return DecodeCompactFieldMaskPaths(data.str(), callback.get());
}
@@ -1188,6 +1204,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece(
type_url = GetFullTypeWithUrl(master_type_.name());
} else {
if (element_->IsMap() || element_->IsStructMap()) {
+ if (!ValidMapKey(name)) return this;
is_map_entry = true;
field = StartMapEntry(name);
} else {
@@ -1462,6 +1479,19 @@ bool ProtoStreamObjectWriter::ValidOneof(const google::protobuf::Field& field,
return true;
}
+bool ProtoStreamObjectWriter::ValidMapKey(StringPiece unnormalized_name) {
+ if (element_ == NULL) return true;
+
+ if (!element_->InsertMapKeyIfNotPresent(unnormalized_name)) {
+ InvalidName(
+ unnormalized_name,
+ StrCat("Repeated map key: '", unnormalized_name, "' is already set."));
+ return false;
+ }
+
+ return true;
+}
+
const google::protobuf::Field* ProtoStreamObjectWriter::BeginNamed(
StringPiece name, bool is_list) {
if (invalid_depth_ > 0) {
@@ -1614,6 +1644,7 @@ void ProtoStreamObjectWriter::WriteTag(const google::protobuf::Field& field) {
stream_->WriteTag(WireFormatLite::MakeTag(field.number(), wire_type));
}
+
} // namespace converter
} // namespace util
} // namespace protobuf
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h
index 8f49120b..19f747fe 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.h
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.h
@@ -259,6 +259,13 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
// generate an error.
void TakeOneofIndex(int32 index);
+ // Inserts map key into hash set if and only if the key did NOT already
+ // exist in hash set.
+ // The hash set (map_keys_) is ONLY used to keep track of map keys.
+ // Return true if insert successfully; returns false if the map key was
+ // already present.
+ bool InsertMapKeyIfNotPresent(StringPiece map_key);
+
private:
// Used for access to variables of the enclosing instance of
// ProtoStreamObjectWriter.
@@ -296,6 +303,10 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
// incoming messages so no more than one oneof is set.
hash_set<int32> oneof_indices_;
+ // Set of map keys already seen for the type_. Used to validate incoming
+ // messages so no map key appears more than once.
+ hash_set<StringPiece> map_keys_;
+
GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoElement);
};
@@ -378,6 +389,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
// Helper method to write proto tags based on the given field.
void WriteTag(const google::protobuf::Field& field);
+
// Helper function to render primitive data types in DataPiece.
void RenderSimpleDataPiece(const google::protobuf::Field& field,
const google::protobuf::Type& type,
@@ -424,6 +436,14 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
bool ValidOneof(const google::protobuf::Field& field,
StringPiece unnormalized_name);
+ // Returns true if the map key for type_ is not duplicated key.
+ // If map key is duplicated key, this function returns false.
+ // Note that caller should make sure that the current proto element (element_)
+ // is of element type MAP or STRUCT_MAP.
+ // It also calls the appropriate error callback and unnormalzied_name is used
+ // for error string.
+ bool ValidMapKey(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.
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
index 96e5ccfb..cb9f97f7 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
@@ -45,6 +45,7 @@
#include <google/protobuf/util/internal/testdata/field_mask.pb.h>
#include <google/protobuf/util/internal/type_info_test_helper.h>
#include <google/protobuf/util/internal/constants.h>
+#include <google/protobuf/util/message_differencer.h>
#include <google/protobuf/stubs/bytestream.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/util/internal/testdata/anys.pb.h>
@@ -139,7 +140,9 @@ class BaseProtoStreamObjectWriterTest
google::protobuf::scoped_ptr<Message> message(expected.New());
message->ParsePartialFromIstream(&istream);
- EXPECT_EQ(expected.DebugString(), message->DebugString());
+ if (!MessageDifferencer::Equivalent(expected, *message)) {
+ EXPECT_EQ(expected.DebugString(), message->DebugString());
+ }
}
void CheckOutput(const Message& expected) { CheckOutput(expected, -1); }
@@ -156,7 +159,12 @@ class BaseProtoStreamObjectWriterTest
MATCHER_P(HasObjectLocation, expected,
"Verifies the expected object location") {
- string actual = std::tr1::get<0>(arg).ToString();
+ string actual;
+#if __cplusplus >= 201103L
+ actual = std::get<0>(arg).ToString();
+#else
+ actual = std::tr1::get<0>(arg).ToString();
+#endif
if (actual.compare(expected) == 0) return true;
*result_listener << "actual location is: " << actual;
return false;
@@ -851,15 +859,19 @@ class ProtoStreamObjectWriterTimestampDurationTest
}
};
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+ ProtoStreamObjectWriterTimestampDurationTest,
+ ::testing::Values(
+ testing::USE_TYPE_RESOLVER));
+
TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError1) {
TimestampDuration timestamp;
EXPECT_CALL(
listener_,
- InvalidValue(
- _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
- StringPiece("Field 'ts', Illegal timestamp format; timestamps "
- "must end with 'Z'")));
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+ StringPiece("Field 'ts', Invalid time format: ")));
ow_->StartObject("")->RenderString("ts", "")->EndObject();
CheckOutput(timestamp);
@@ -870,10 +882,9 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError2) {
EXPECT_CALL(
listener_,
- InvalidValue(
- _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
- StringPiece(
- "Field 'ts', Invalid time format: Failed to parse input")));
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+ StringPiece("Field 'ts', Invalid time format: Z")));
ow_->StartObject("")->RenderString("ts", "Z")->EndObject();
CheckOutput(timestamp);
@@ -884,10 +895,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: "
+ "1970-01-01T00:00:00.ABZ")));
ow_->StartObject("")
->RenderString("ts", "1970-01-01T00:00:00.ABZ")
@@ -902,7 +913,8 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError4) {
listener_,
InvalidValue(_,
StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
- StringPiece("Field 'ts', Timestamp value exceeds limits")));
+ StringPiece("Field 'ts', Invalid time format: "
+ "-8032-10-18T00:00:00.000Z")));
ow_->StartObject("")
->RenderString("ts", "-8032-10-18T00:00:00.000Z")
@@ -1008,6 +1020,11 @@ class ProtoStreamObjectWriterStructTest
}
};
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+ ProtoStreamObjectWriterStructTest,
+ ::testing::Values(
+ testing::USE_TYPE_RESOLVER));
+
// TODO(skarvaje): Write tests for failure cases.
TEST_P(ProtoStreamObjectWriterStructTest, StructRenderSuccess) {
StructType struct_type;
@@ -1046,12 +1063,62 @@ TEST_P(ProtoStreamObjectWriterStructTest, StructInvalidInputFailure) {
CheckOutput(struct_type);
}
+TEST_P(ProtoStreamObjectWriterStructTest, SimpleRepeatedStructMapKeyTest) {
+ EXPECT_CALL(
+ listener_,
+ InvalidName(_, StringPiece("k1"),
+ StringPiece("Repeated map key: 'k1' is already set.")));
+ ow_->StartObject("")
+ ->StartObject("object")
+ ->RenderString("k1", "v1")
+ ->RenderString("k1", "v2")
+ ->EndObject()
+ ->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterStructTest, RepeatedStructMapListKeyTest) {
+ EXPECT_CALL(
+ listener_,
+ InvalidName(_, StringPiece("k1"),
+ StringPiece("Repeated map key: 'k1' is already set.")));
+ ow_->StartObject("")
+ ->StartObject("object")
+ ->RenderString("k1", "v1")
+ ->StartList("k1")
+ ->RenderString("", "v2")
+ ->EndList()
+ ->EndObject()
+ ->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterStructTest, RepeatedStructMapObjectKeyTest) {
+ EXPECT_CALL(
+ listener_,
+ InvalidName(_, StringPiece("k1"),
+ StringPiece("Repeated map key: 'k1' is already set.")));
+ ow_->StartObject("")
+ ->StartObject("object")
+ ->StartObject("k1")
+ ->RenderString("sub_k1", "v1")
+ ->EndObject()
+ ->StartObject("k1")
+ ->RenderString("sub_k2", "v2")
+ ->EndObject()
+ ->EndObject()
+ ->EndObject();
+}
+
class ProtoStreamObjectWriterMapTest : public BaseProtoStreamObjectWriterTest {
protected:
ProtoStreamObjectWriterMapTest()
: BaseProtoStreamObjectWriterTest(MapIn::descriptor()) {}
};
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+ ProtoStreamObjectWriterMapTest,
+ ::testing::Values(
+ testing::USE_TYPE_RESOLVER));
+
TEST_P(ProtoStreamObjectWriterMapTest, MapShouldNotAcceptList) {
MapIn mm;
EXPECT_CALL(listener_,
@@ -1066,17 +1133,37 @@ TEST_P(ProtoStreamObjectWriterMapTest, MapShouldNotAcceptList) {
CheckOutput(mm);
}
+TEST_P(ProtoStreamObjectWriterMapTest, RepeatedMapKeyTest) {
+ EXPECT_CALL(
+ listener_,
+ InvalidName(_, StringPiece("k1"),
+ StringPiece("Repeated map key: 'k1' is already set.")));
+ ow_->StartObject("")
+ ->RenderString("other", "test")
+ ->StartObject("map_input")
+ ->RenderString("k1", "v1")
+ ->RenderString("k1", "v2")
+ ->EndObject()
+ ->EndObject();
+}
+
class ProtoStreamObjectWriterAnyTest : public BaseProtoStreamObjectWriterTest {
protected:
ProtoStreamObjectWriterAnyTest() {
vector<const Descriptor*> descriptors;
descriptors.push_back(AnyOut::descriptor());
descriptors.push_back(google::protobuf::DoubleValue::descriptor());
+ descriptors.push_back(google::protobuf::Timestamp::descriptor());
descriptors.push_back(google::protobuf::Any::descriptor());
ResetTypeInfo(descriptors);
}
};
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+ ProtoStreamObjectWriterAnyTest,
+ ::testing::Values(
+ testing::USE_TYPE_RESOLVER));
+
TEST_P(ProtoStreamObjectWriterAnyTest, AnyRenderSuccess) {
AnyOut any;
google::protobuf::Any* any_type = any.mutable_any();
@@ -1119,8 +1206,6 @@ TEST_P(ProtoStreamObjectWriterAnyTest, RecursiveAny) {
->EndObject()
->EndObject()
->EndObject();
-
- CheckOutput(out, 115);
}
TEST_P(ProtoStreamObjectWriterAnyTest, DoubleRecursiveAny) {
@@ -1155,8 +1240,6 @@ TEST_P(ProtoStreamObjectWriterAnyTest, DoubleRecursiveAny) {
->EndObject()
->EndObject()
->EndObject();
-
- CheckOutput(out, 159);
}
TEST_P(ProtoStreamObjectWriterAnyTest, EmptyAnyFromEmptyObject) {
@@ -1263,6 +1346,23 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyNullInputFails) {
CheckOutput(any);
}
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypeErrorTest) {
+ EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"),
+ StringPiece("Invalid time format: ")));
+
+ AnyOut any;
+ google::protobuf::Any* any_type = any.mutable_any();
+ any_type->set_type_url("type.googleapis.com/google.protobuf.Timestamp");
+
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Timestamp")
+ ->RenderString("value", "")
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(any);
+}
+
class ProtoStreamObjectWriterFieldMaskTest
: public BaseProtoStreamObjectWriterTest {
protected:
@@ -1274,6 +1374,11 @@ class ProtoStreamObjectWriterFieldMaskTest
}
};
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+ ProtoStreamObjectWriterFieldMaskTest,
+ ::testing::Values(
+ testing::USE_TYPE_RESOLVER));
+
TEST_P(ProtoStreamObjectWriterFieldMaskTest, SimpleFieldMaskTest) {
FieldMaskTest expected;
expected.set_id("1");
@@ -1683,6 +1788,7 @@ TEST_P(ProtoStreamObjectWriterOneOfsTest,
ow_->RenderString("strData", "blah");
ow_->RenderInt32("intData", 123);
ow_->EndObject();
+ ow_->EndObject();
}
} // namespace converter
diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc
index 5d7dcc87..61899c24 100644
--- a/src/google/protobuf/util/internal/utility.cc
+++ b/src/google/protobuf/util/internal/utility.cc
@@ -298,16 +298,21 @@ bool IsMap(const google::protobuf::Field& field,
"google.protobuf.MessageOptions.map_entry", false));
}
+bool IsMessageSetWireFormat(const google::protobuf::Type& type) {
+ return GetBoolOptionOrDefault(
+ type.options(), "google.protobuf.MessageOptions.message_set_wire_format", false);
+}
+
string DoubleAsString(double value) {
- if (google::protobuf::MathLimits<double>::IsPosInf(value)) return "Infinity";
- if (google::protobuf::MathLimits<double>::IsNegInf(value)) return "-Infinity";
- if (google::protobuf::MathLimits<double>::IsNaN(value)) return "NaN";
+ if (MathLimits<double>::IsPosInf(value)) return "Infinity";
+ if (MathLimits<double>::IsNegInf(value)) return "-Infinity";
+ if (MathLimits<double>::IsNaN(value)) return "NaN";
return SimpleDtoa(value);
}
string FloatAsString(float value) {
- if (google::protobuf::MathLimits<float>::IsFinite(value)) return SimpleFtoa(value);
+ if (MathLimits<float>::IsFinite(value)) return SimpleFtoa(value);
return DoubleAsString(value);
}
@@ -318,7 +323,7 @@ bool SafeStrToFloat(StringPiece str, float *value) {
}
*value = static_cast<float>(double_value);
- if (google::protobuf::MathLimits<float>::IsInf(*value)) {
+ if (MathLimits<float>::IsInf(*value)) {
return false;
}
return true;
diff --git a/src/google/protobuf/util/internal/utility.h b/src/google/protobuf/util/internal/utility.h
index 87f7602a..5ba97bd2 100644
--- a/src/google/protobuf/util/internal/utility.h
+++ b/src/google/protobuf/util/internal/utility.h
@@ -138,9 +138,6 @@ const google::protobuf::EnumValue* FindEnumValueByNumberOrNull(
const google::protobuf::Enum* enum_type, int32 value);
// Converts input to camel-case and returns it.
-// Tests are in wrappers/translator/snake2camel_objectwriter_test.cc
-// TODO(skarvaje): Isolate tests for this function and put them in
-// utility_test.cc
LIBPROTOBUF_EXPORT string ToCamelCase(const StringPiece input);
// Converts input to snake_case and returns it.
@@ -157,6 +154,9 @@ LIBPROTOBUF_EXPORT bool IsValidBoolString(const string& bool_string);
LIBPROTOBUF_EXPORT bool IsMap(const google::protobuf::Field& field,
const google::protobuf::Type& type);
+// Returns true if the given type has special MessageSet wire format.
+bool IsMessageSetWireFormat(const google::protobuf::Type& type);
+
// Infinity/NaN-aware conversion to string.
LIBPROTOBUF_EXPORT string DoubleAsString(double value);
LIBPROTOBUF_EXPORT string FloatAsString(float value);
diff --git a/src/google/protobuf/util/json_format_proto3.proto b/src/google/protobuf/util/json_format_proto3.proto
index 7a282868..e8137677 100644
--- a/src/google/protobuf/util/json_format_proto3.proto
+++ b/src/google/protobuf/util/json_format_proto3.proto
@@ -100,6 +100,16 @@ message TestMap {
map<string, int32> string_map = 6;
}
+message TestNestedMap {
+ map<bool, int32> bool_map = 1;
+ map<int32, int32> int32_map = 2;
+ map<int64, int32> int64_map = 3;
+ map<uint32, int32> uint32_map = 4;
+ map<uint64, int32> uint64_map = 5;
+ map<string, int32> string_map = 6;
+ map<string, TestNestedMap> map_map = 7;
+}
+
message TestWrapper {
google.protobuf.BoolValue bool_value = 1;
google.protobuf.Int32Value int32_value = 2;
diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc
index 6cd40fd5..c3b8d502 100644
--- a/src/google/protobuf/util/json_util.cc
+++ b/src/google/protobuf/util/json_util.cc
@@ -34,7 +34,6 @@
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/util/internal/default_value_objectwriter.h>
-#include <google/protobuf/util/internal/snake2camel_objectwriter.h>
#include <google/protobuf/util/internal/error_listener.h>
#include <google/protobuf/util/internal/json_objectwriter.h>
#include <google/protobuf/util/internal/json_stream_parser.h>
@@ -83,13 +82,12 @@ util::Status BinaryToJsonStream(TypeResolver* resolver,
io::CodedOutputStream out_stream(json_output);
converter::JsonObjectWriter json_writer(options.add_whitespace ? " " : "",
&out_stream);
- converter::Snake2CamelObjectWriter snake2camel_writer(&json_writer);
if (options.always_print_primitive_fields) {
converter::DefaultValueObjectWriter default_value_writer(
- resolver, type, &snake2camel_writer);
+ resolver, type, &json_writer);
return proto_source.WriteTo(&default_value_writer);
} else {
- return proto_source.WriteTo(&snake2camel_writer);
+ return proto_source.WriteTo(&json_writer);
}
}
diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc
index f4dc3562..da68495f 100644
--- a/src/google/protobuf/util/json_util_test.cc
+++ b/src/google/protobuf/util/json_util_test.cc
@@ -163,7 +163,7 @@ typedef pair<char*, int> Segment;
class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream {
public:
explicit SegmentedZeroCopyOutputStream(list<Segment> segments)
- : segments_(segments), last_segment_(NULL, 0), byte_count_(0) {}
+ : segments_(segments), last_segment_(static_cast<char*>(NULL), 0), byte_count_(0) {}
virtual bool Next(void** buffer, int* length) {
if (segments_.empty()) {
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
index d709da57..47237e5a 100644
--- a/src/google/protobuf/util/message_differencer.cc
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -946,6 +946,18 @@ bool MessageDifferencer::IsIgnored(
return false;
}
+bool MessageDifferencer::IsUnknownFieldIgnored(
+ const Message& message1, const Message& message2,
+ const SpecificField& field, const vector<SpecificField>& parent_fields) {
+ for (int i = 0; i < ignore_criteria_.size(); ++i) {
+ if (ignore_criteria_[i]->IsUnknownFieldIgnored(message1, message2, field,
+ parent_fields)) {
+ return true;
+ }
+ }
+ return false;
+}
+
const MessageDifferencer::MapKeyComparator* MessageDifferencer
::GetMapKeyComparator(const FieldDescriptor* field) {
if (!field->is_repeated()) return NULL;
@@ -1127,15 +1139,6 @@ bool MessageDifferencer::CompareUnknownFields(
continue;
}
- if (change_type == ADDITION || change_type == DELETION ||
- change_type == MODIFICATION) {
- if (reporter_ == NULL) {
- // We found a difference and we have no reproter.
- return false;
- }
- is_different = true;
- }
-
// Build the SpecificField. This is slightly complicated.
SpecificField specific_field;
specific_field.unknown_field_number = focus_field->number();
@@ -1160,6 +1163,25 @@ bool MessageDifferencer::CompareUnknownFields(
specific_field.new_index = index2 - current_repeated_start2;
}
+ if (IsUnknownFieldIgnored(message1, message2, specific_field,
+ *parent_field)) {
+ if (reporter_ != NULL) {
+ parent_field->push_back(specific_field);
+ reporter_->ReportUnknownFieldIgnored(message1, message2, *parent_field);
+ parent_field->pop_back();
+ }
+ return true;
+ }
+
+ if (change_type == ADDITION || change_type == DELETION ||
+ change_type == MODIFICATION) {
+ if (reporter_ == NULL) {
+ // We found a difference and we have no reproter.
+ return false;
+ }
+ is_different = true;
+ }
+
parent_field->push_back(specific_field);
switch (change_type) {
@@ -1341,9 +1363,11 @@ bool MessageDifferencer::MatchRepeatedFieldIndices(
// doesn't neccessarily imply Compare(b, c). Therefore a naive greedy
// algorithm will fail to find a maximum matching.
// Here we use the argumenting path algorithm.
- MaximumMatcher::NodeMatchCallback* callback = NewPermanentCallback(
- this, &MessageDifferencer::IsMatch, repeated_field, key_comparator,
- &message1, &message2, parent_fields);
+ MaximumMatcher::NodeMatchCallback* callback =
+ google::protobuf::internal::NewPermanentCallback(
+ this, &MessageDifferencer::IsMatch,
+ repeated_field, key_comparator,
+ &message1, &message2, parent_fields);
MaximumMatcher matcher(count1, count2, callback, match_list1,
match_list2);
// If diff info is not needed, we should end the matching process as
@@ -1625,6 +1649,18 @@ void MessageDifferencer::StreamReporter::ReportIgnored(
printer_->Print("\n"); // Print for newlines.
}
+void MessageDifferencer::StreamReporter::ReportUnknownFieldIgnored(
+ const Message& message1, const Message& message2,
+ const vector<SpecificField>& field_path) {
+ printer_->Print("ignored: ");
+ PrintPath(field_path, true);
+ if (CheckPathChanged(field_path)) {
+ printer_->Print(" -> ");
+ PrintPath(field_path, false);
+ }
+ printer_->Print("\n"); // Print for newlines.
+}
+
} // namespace util
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h
index e002a0f3..34c173db 100644
--- a/src/google/protobuf/util/message_differencer.h
+++ b/src/google/protobuf/util/message_differencer.h
@@ -278,6 +278,13 @@ class LIBPROTOBUF_EXPORT MessageDifferencer {
const Message& message2,
const vector<SpecificField>& field_path) { }
+ // Report that an unkown field is ignored. (see comment above).
+ // Note this is a different function since the last SpecificField in field
+ // path has a null field. This could break existing Reporter.
+ virtual void ReportUnknownFieldIgnored(
+ const Message& message1, const Message& message2,
+ const vector<SpecificField>& field_path) {}
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reporter);
};
@@ -317,6 +324,16 @@ class LIBPROTOBUF_EXPORT MessageDifferencer {
const Message& message2,
const FieldDescriptor* field,
const vector<SpecificField>& parent_fields) = 0;
+
+ // Returns true if the unknown field should be ignored.
+ // Note: This will be called for unknown fields as well in which case
+ // field.field will be null.
+ virtual bool IsUnknownFieldIgnored(
+ const Message& message1, const Message& message2,
+ const SpecificField& field,
+ const vector<SpecificField>& parent_fields) {
+ return false;
+ }
};
// To add a Reporter, construct default here, then use ReportDifferencesTo or
@@ -583,6 +600,10 @@ class LIBPROTOBUF_EXPORT MessageDifferencer {
const Message& message2,
const vector<SpecificField>& field_path);
+ virtual void ReportUnknownFieldIgnored(
+ const Message& message1, const Message& message2,
+ const vector<SpecificField>& field_path);
+
protected:
// Prints the specified path of fields to the buffer.
virtual void PrintPath(const vector<SpecificField>& field_path,
@@ -722,6 +743,12 @@ class LIBPROTOBUF_EXPORT MessageDifferencer {
const FieldDescriptor* field,
const vector<SpecificField>& parent_fields);
+ // Returns true if this unknown field is to be ignored when this
+ // MessageDifferencer compares messages.
+ bool IsUnknownFieldIgnored(const Message& message1, const Message& message2,
+ const SpecificField& field,
+ const vector<SpecificField>& parent_fields);
+
// Returns MapKeyComparator* when this field has been configured to
// be treated as a map. If not, returns NULL.
const MapKeyComparator* GetMapKeyComparator(const FieldDescriptor* field);
diff --git a/src/google/protobuf/util/time_util.h b/src/google/protobuf/util/time_util.h
index 58dbf8e6..1bac0897 100644
--- a/src/google/protobuf/util/time_util.h
+++ b/src/google/protobuf/util/time_util.h
@@ -41,7 +41,6 @@
#endif
#include <google/protobuf/duration.pb.h>
-#include <google/protobuf/stubs/port.h>
#include <google/protobuf/timestamp.pb.h>
namespace google {
@@ -243,10 +242,8 @@ inline ostream& operator<<(ostream& out, const Duration& d) {
// Overloaded operators for Timestamp
//
// Assignement operators.
-LIBPROTOBUF_EXPORT
-Timestamp& operator+=(Timestamp& t, const Duration& d); // NOLINT
-LIBPROTOBUF_EXPORT
-Timestamp& operator-=(Timestamp& t, const Duration& d); // NOLINT
+LIBPROTOBUF_EXPORT Timestamp& operator+=(Timestamp& t, const Duration& d); // NOLINT
+LIBPROTOBUF_EXPORT Timestamp& operator-=(Timestamp& t, const Duration& d); // NOLINT
// Relational operators.
inline bool operator<(const Timestamp& t1, const Timestamp& t2) {
if (t1.seconds() == t2.seconds()) {
diff --git a/src/google/protobuf/util/type_resolver_util.cc b/src/google/protobuf/util/type_resolver_util.cc
index 908634eb..a0996954 100644
--- a/src/google/protobuf/util/type_resolver_util.cc
+++ b/src/google/protobuf/util/type_resolver_util.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/wrappers.pb.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/util/internal/utility.h>
#include <google/protobuf/util/type_resolver.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/status.h>
@@ -53,8 +54,7 @@ using util::Status;
using util::error::INVALID_ARGUMENT;
using util::error::NOT_FOUND;
-bool SplitTypeUrl(const string& type_url,
- string* url_prefix,
+bool SplitTypeUrl(const string& type_url, string* url_prefix,
string* message_name) {
size_t pos = type_url.find_last_of("/");
if (pos == string::npos) {
@@ -65,60 +65,19 @@ 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:
DescriptorPoolTypeResolver(const string& url_prefix,
const DescriptorPool* pool)
- : url_prefix_(url_prefix), pool_(pool) {
- }
+ : url_prefix_(url_prefix), pool_(pool) {}
Status ResolveMessageType(const string& type_url, Type* type) {
string url_prefix, message_name;
if (!SplitTypeUrl(type_url, &url_prefix, &message_name) ||
url_prefix != url_prefix_) {
- return Status(INVALID_ARGUMENT, "Failed to parse type url: " + type_url);
+ return Status(INVALID_ARGUMENT,
+ StrCat("Invalid type URL, type URLs must be of the form '",
+ url_prefix_, "/<typename>', got: ", type_url));
}
if (url_prefix != url_prefix_) {
return Status(INVALID_ARGUMENT,
@@ -126,7 +85,8 @@ class DescriptorPoolTypeResolver : public TypeResolver {
}
const Descriptor* descriptor = pool_->FindMessageTypeByName(message_name);
if (descriptor == NULL) {
- return Status(NOT_FOUND, "Cannot found the type: " + message_name);
+ return Status(NOT_FOUND,
+ "Invalid type URL, unknown type: " + message_name);
}
ConvertDescriptor(descriptor, type);
return Status();
@@ -136,7 +96,9 @@ class DescriptorPoolTypeResolver : public TypeResolver {
string url_prefix, type_name;
if (!SplitTypeUrl(type_url, &url_prefix, &type_name) ||
url_prefix != url_prefix_) {
- return Status(INVALID_ARGUMENT, "Failed to parse type url: " + type_url);
+ return Status(INVALID_ARGUMENT,
+ StrCat("Invalid type URL, type URLs must be of the form '",
+ url_prefix_, "/<typename>', got: ", type_url));
}
if (url_prefix != url_prefix_) {
return Status(INVALID_ARGUMENT,
@@ -144,7 +106,7 @@ class DescriptorPoolTypeResolver : public TypeResolver {
}
const EnumDescriptor* descriptor = pool_->FindEnumTypeByName(type_name);
if (descriptor == NULL) {
- return Status(NOT_FOUND, "Cannot found the type: " + type_name);
+ return Status(NOT_FOUND, "Invalid type URL, unknown type: " + type_name);
}
ConvertEnumDescriptor(descriptor, enum_type);
return Status();
@@ -197,7 +159,7 @@ class DescriptorPoolTypeResolver : public TypeResolver {
}
field->set_number(descriptor->number());
field->set_name(descriptor->name());
- field->set_json_name(ToCamelCase(descriptor->name()));
+ field->set_json_name(converter::ToCamelCase(descriptor->name()));
if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE) {
field->set_type_url(GetTypeUrl(descriptor->message_type()));
} else if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
@@ -221,8 +183,7 @@ class DescriptorPoolTypeResolver : public TypeResolver {
descriptor->file()->name());
for (int i = 0; i < descriptor->value_count(); ++i) {
const EnumValueDescriptor* value_descriptor = descriptor->value(i);
- EnumValue* value =
- enum_type->mutable_enumvalue()->Add();
+ EnumValue* value = enum_type->mutable_enumvalue()->Add();
value->set_name(value_descriptor->name());
value->set_number(value_descriptor->number());
@@ -245,8 +206,8 @@ class DescriptorPoolTypeResolver : public TypeResolver {
} // namespace
-TypeResolver* NewTypeResolverForDescriptorPool(
- const string& url_prefix, const DescriptorPool* pool) {
+TypeResolver* NewTypeResolverForDescriptorPool(const string& url_prefix,
+ const DescriptorPool* pool) {
return new DescriptorPoolTypeResolver(url_prefix, pool);
}