aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/google/protobuf/api.pb.cc2
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc2
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_extension.cc2
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_field.cc2
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_file.cc227
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers.cc72
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers.h12
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_map_field.cc2
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_message.cc16
-rw-r--r--src/google/protobuf/compiler/parser.cc1
-rw-r--r--src/google/protobuf/descriptor.pb.cc18
-rw-r--r--src/google/protobuf/duration.pb.cc2
-rw-r--r--src/google/protobuf/timestamp.pb.cc2
-rw-r--r--src/google/protobuf/type.pb.cc2
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter.cc5
-rw-r--r--src/google/protobuf/util/json_util_test.cc28
16 files changed, 314 insertions, 81 deletions
diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc
index cfb30786..e8c2a178 100644
--- a/src/google/protobuf/api.pb.cc
+++ b/src/google/protobuf/api.pb.cc
@@ -1005,7 +1005,7 @@ void Method::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 69f216ab..69cd5f3c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -2419,7 +2419,7 @@ GenerateClear(io::Printer* printer) {
" &reinterpret_cast<$classname$*>(16)->f)\n"
"#endif\n\n"
"#define ZR_(first, last) do {\\\n"
- " ::memset(&first, 0,\\\n"
+ " ::memset(&(first), 0,\\\n"
" ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\\\n"
"} while (0)\n\n";
for (int i = 0; i < runs_of_fields_.size(); i++) {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
index c0e7253a..d0de1eca 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
@@ -85,7 +85,7 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization(
if (descriptor_->containing_type()->options().message_set_wire_format())
options.push_back("GPBExtensionSetWireFormat");
- vars["options"] = BuildFlagsString(options);
+ vars["options"] = BuildFlagsString(FLAGTYPE_EXTENSION, options);
ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
string singular_type;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
index d2a6e882..527b7c0c 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
@@ -93,7 +93,7 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
field_flags.push_back("GPBFieldHasEnumDescriptor");
}
- (*variables)["fieldflags"] = BuildFlagsString(field_flags);
+ (*variables)["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags);
(*variables)["default"] = DefaultValue(descriptor);
(*variables)["default_name"] = GPBGenericValueFieldName(descriptor);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
index 6d889e63..878a3743 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
@@ -37,6 +37,7 @@
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/stl_util.h>
#include <google/protobuf/stubs/strutil.h>
+#include <algorithm> // std::find()
#include <iostream>
#include <sstream>
@@ -45,16 +46,118 @@
namespace google {
namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
// This is also found in GPBBootstrap.h, and needs to be kept in sync. It
// is the version check done to ensure generated code works with the current
// runtime being used.
-const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30001;
+const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30002;
const char* kHeaderExtension = ".pbobjc.h";
-namespace compiler {
-namespace objectivec {
+// Checks if a message contains any extension definitions (on the message or
+// a nested message under it).
+bool MessageContainsExtensions(const Descriptor* message) {
+ if (message->extension_count() > 0) {
+ return true;
+ }
+ for (int i = 0; i < message->nested_type_count(); i++) {
+ if (MessageContainsExtensions(message->nested_type(i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Checks if the file contains any extensions definitions (at the root or
+// nested under a message).
+bool FileContainsExtensions(const FileDescriptor* file) {
+ if (file->extension_count() > 0) {
+ return true;
+ }
+ for (int i = 0; i < file->message_type_count(); i++) {
+ if (MessageContainsExtensions(file->message_type(i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Helper for CollectMinimalFileDepsContainingExtensionsWorker that marks all
+// deps as visited and prunes them from the needed files list.
+void PruneFileAndDepsMarkingAsVisited(
+ const FileDescriptor* file,
+ vector<const FileDescriptor*>* files,
+ set<const FileDescriptor*>* files_visited) {
+ vector<const FileDescriptor*>::iterator iter =
+ std::find(files->begin(), files->end(), file);
+ if (iter != files->end()) {
+ files->erase(iter);
+ }
+ files_visited->insert(file);
+ for (int i = 0; i < file->dependency_count(); i++) {
+ PruneFileAndDepsMarkingAsVisited(file->dependency(i), files, files_visited);
+ }
+}
+
+// Helper for CollectMinimalFileDepsContainingExtensions.
+void CollectMinimalFileDepsContainingExtensionsWorker(
+ const FileDescriptor* file,
+ vector<const FileDescriptor*>* files,
+ set<const FileDescriptor*>* files_visited) {
+ if (files_visited->find(file) != files_visited->end()) {
+ return;
+ }
+ files_visited->insert(file);
+
+ if (FileContainsExtensions(file)) {
+ files->push_back(file);
+ for (int i = 0; i < file->dependency_count(); i++) {
+ const FileDescriptor* dep = file->dependency(i);
+ PruneFileAndDepsMarkingAsVisited(dep, files, files_visited);
+ }
+ } else {
+ for (int i = 0; i < file->dependency_count(); i++) {
+ const FileDescriptor* dep = file->dependency(i);
+ CollectMinimalFileDepsContainingExtensionsWorker(dep, files,
+ files_visited);
+ }
+ }
+}
+
+// Collect the deps of the given file that contain extensions. This can be used to
+// create the chain of roots that need to be wired together.
+//
+// NOTE: If any changes are made to this and the supporting functions, you will
+// need to manually validate what the generated code is for the test files:
+// objectivec/Tests/unittest_extension_chain_*.proto
+// There are comments about what the expected code should be line and limited
+// testing objectivec/Tests/GPBUnittestProtos2.m around compilation (#imports
+// specifically).
+void CollectMinimalFileDepsContainingExtensions(
+ const FileDescriptor* file,
+ vector<const FileDescriptor*>* files) {
+ set<const FileDescriptor*> files_visited;
+ for (int i = 0; i < file->dependency_count(); i++) {
+ const FileDescriptor* dep = file->dependency(i);
+ CollectMinimalFileDepsContainingExtensionsWorker(dep, files,
+ &files_visited);
+ }
+}
+
+bool IsDirectDependency(const FileDescriptor* dep, const FileDescriptor* file) {
+ for (int i = 0; i < file->dependency_count(); i++) {
+ if (dep == file->dependency(i)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options)
: file_(file),
@@ -204,6 +307,9 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
// #import the runtime support.
PrintFileRuntimePreamble(printer, "GPBProtocolBuffers_RuntimeSupport.h");
+ vector<const FileDescriptor*> deps_with_extensions;
+ CollectMinimalFileDepsContainingExtensions(file_, &deps_with_extensions);
+
{
ImportWriter import_writer(
options_.generate_for_named_framework,
@@ -227,6 +333,18 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
}
}
+ // If any indirect dependency provided extensions, it needs to be directly
+ // imported so it can get merged into the root's extensions registry.
+ // See the Note by CollectMinimalFileDepsContainingExtensions before
+ // changing this.
+ for (vector<const FileDescriptor *>::iterator iter =
+ deps_with_extensions.begin();
+ iter != deps_with_extensions.end(); ++iter) {
+ if (!IsDirectDependency(*iter, file_)) {
+ import_writer.AddFile(*iter, header_extension);
+ }
+ }
+
import_writer.Print(printer);
}
@@ -263,29 +381,11 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
"@implementation $root_class_name$\n\n",
"root_class_name", root_class_name_);
- // Generate the extension initialization structures for the top level and
- // any nested messages.
- ostringstream extensions_stringstream;
- if (file_->extension_count() + file_->message_type_count() > 0) {
- io::OstreamOutputStream extensions_outputstream(&extensions_stringstream);
- io::Printer extensions_printer(&extensions_outputstream, '$');
- for (vector<ExtensionGenerator *>::iterator iter =
- extension_generators_.begin();
- iter != extension_generators_.end(); ++iter) {
- (*iter)->GenerateStaticVariablesInitialization(&extensions_printer);
- }
- for (vector<MessageGenerator *>::iterator iter =
- message_generators_.begin();
- iter != message_generators_.end(); ++iter) {
- (*iter)->GenerateStaticVariablesInitialization(&extensions_printer);
- }
- extensions_stringstream.flush();
- }
+ const bool file_contains_extensions = FileContainsExtensions(file_);
// If there were any extensions or this file has any dependencies, output
// a registry to override to create the file specific registry.
- const string& extensions_str = extensions_stringstream.str();
- if (extensions_str.length() > 0 || file_->dependency_count() > 0) {
+ if (file_contains_extensions || !deps_with_extensions.empty()) {
printer->Print(
"+ (GPBExtensionRegistry*)extensionRegistry {\n"
" // This is called by +initialize so there is no need to worry\n"
@@ -298,11 +398,20 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
printer->Indent();
printer->Indent();
- if (extensions_str.length() > 0) {
+ if (file_contains_extensions) {
printer->Print(
"static GPBExtensionDescription descriptions[] = {\n");
printer->Indent();
- printer->Print(extensions_str.c_str());
+ for (vector<ExtensionGenerator *>::iterator iter =
+ extension_generators_.begin();
+ iter != extension_generators_.end(); ++iter) {
+ (*iter)->GenerateStaticVariablesInitialization(printer);
+ }
+ for (vector<MessageGenerator *>::iterator iter =
+ message_generators_.begin();
+ iter != message_generators_.end(); ++iter) {
+ (*iter)->GenerateStaticVariablesInitialization(printer);
+ }
printer->Outdent();
printer->Print(
"};\n"
@@ -315,11 +424,21 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
"}\n");
}
- for (int i = 0; i < file_->dependency_count(); i++) {
- const string root_class_name(FileClassName(file_->dependency(i)));
+ if (deps_with_extensions.empty()) {
+ printer->Print(
+ "// None of the imports (direct or indirect) defined extensions, so no need to add\n"
+ "// them to this registry.\n");
+ } else {
printer->Print(
- "[registry addExtensions:[$dependency$ extensionRegistry]];\n",
- "dependency", root_class_name);
+ "// Merge in the imports (direct or indirect) that defined extensions.\n");
+ for (vector<const FileDescriptor *>::iterator iter =
+ deps_with_extensions.begin();
+ iter != deps_with_extensions.end(); ++iter) {
+ const string root_class_name(FileClassName((*iter)));
+ printer->Print(
+ "[registry addExtensions:[$dependency$ extensionRegistry]];\n",
+ "dependency", root_class_name);
+ }
}
printer->Outdent();
@@ -328,27 +447,39 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
printer->Print(
" }\n"
" return registry;\n"
- "}\n"
- "\n");
+ "}\n");
+ } else {
+ if (file_->dependency_count() > 0) {
+ printer->Print(
+ "// No extensions in the file and none of the imports (direct or indirect)\n"
+ "// defined extensions, so no need to generate +extensionRegistry.\n");
+ } else {
+ printer->Print(
+ "// No extensions in the file and no imports, so no need to generate\n"
+ "// +extensionRegistry.\n");
+ }
}
- printer->Print("@end\n\n");
+ printer->Print("\n@end\n\n");
// File descriptor only needed if there are messages to use it.
if (message_generators_.size() > 0) {
- string syntax;
+ map<string, string> vars;
+ vars["root_class_name"] = root_class_name_;
+ vars["package"] = file_->package();
+ vars["objc_prefix"] = FileClassPrefix(file_);
switch (file_->syntax()) {
case FileDescriptor::SYNTAX_UNKNOWN:
- syntax = "GPBFileSyntaxUnknown";
+ vars["syntax"] = "GPBFileSyntaxUnknown";
break;
case FileDescriptor::SYNTAX_PROTO2:
- syntax = "GPBFileSyntaxProto2";
+ vars["syntax"] = "GPBFileSyntaxProto2";
break;
case FileDescriptor::SYNTAX_PROTO3:
- syntax = "GPBFileSyntaxProto3";
+ vars["syntax"] = "GPBFileSyntaxProto3";
break;
}
- printer->Print(
+ printer->Print(vars,
"#pragma mark - $root_class_name$_FileDescriptor\n"
"\n"
"static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n"
@@ -356,16 +487,24 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
" // about thread safety of the singleton.\n"
" static GPBFileDescriptor *descriptor = NULL;\n"
" if (!descriptor) {\n"
- " GPBDebugCheckRuntimeVersion();\n"
- " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
- " syntax:$syntax$];\n"
+ " GPBDebugCheckRuntimeVersion();\n");
+ if (vars["objc_prefix"].size() > 0) {
+ printer->Print(
+ vars,
+ " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
+ " objcPrefix:@\"$objc_prefix$\"\n"
+ " syntax:$syntax$];\n");
+ } else {
+ printer->Print(
+ vars,
+ " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
+ " syntax:$syntax$];\n");
+ }
+ printer->Print(
" }\n"
" return descriptor;\n"
"}\n"
- "\n",
- "root_class_name", root_class_name_,
- "package", file_->package(),
- "syntax", syntax);
+ "\n");
}
for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin();
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
index 847be983..c7fd96ac 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
@@ -210,10 +210,14 @@ const char* const kReservedWordList[] = {
hash_set<string> kReservedWords =
MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList));
-string SanitizeNameForObjC(const string& input, const string& extension) {
+string SanitizeNameForObjC(const string& input,
+ const string& extension,
+ string* out_suffix_added) {
if (kReservedWords.count(input) > 0) {
+ if (out_suffix_added) *out_suffix_added = extension;
return input + extension;
}
+ if (out_suffix_added) out_suffix_added->clear();
return input;
}
@@ -262,6 +266,34 @@ bool IsSpecialName(const string& name, const string* special_names,
return false;
}
+string GetZeroEnumNameForFlagType(const FlagType flag_type) {
+ switch(flag_type) {
+ case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
+ return "GPBDescriptorInitializationFlag_None";
+ case FLAGTYPE_EXTENSION:
+ return "GPBExtensionNone";
+ case FLAGTYPE_FIELD:
+ return "GPBFieldNone";
+ default:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return "0";
+ }
+}
+
+string GetEnumNameForFlagType(const FlagType flag_type) {
+ switch(flag_type) {
+ case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
+ return "GPBDescriptorInitializationFlags";
+ case FLAGTYPE_EXTENSION:
+ return "GPBExtensionOptions";
+ case FLAGTYPE_FIELD:
+ return "GPBFieldFlags";
+ default:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return string();
+ }
+}
+
} // namespace
// Escape C++ trigraphs by escaping question marks to \?
@@ -308,6 +340,12 @@ string BaseFileName(const FileDescriptor* file) {
return basename;
}
+string FileClassPrefix(const FileDescriptor* file) {
+ // Default is empty string, no need to check has_objc_class_prefix.
+ string result = file->options().objc_class_prefix();
+ return result;
+}
+
string FilePath(const FileDescriptor* file) {
string output;
string basename;
@@ -338,19 +376,13 @@ string FilePathBasename(const FileDescriptor* file) {
return output;
}
-string FileClassPrefix(const FileDescriptor* file) {
- // Default is empty string, no need to check has_objc_class_prefix.
- string result = file->options().objc_class_prefix();
- return result;
-}
-
string FileClassName(const FileDescriptor* file) {
string name = FileClassPrefix(file);
name += UnderscoresToCamelCase(StripProto(BaseFileName(file)), true);
name += "Root";
// There aren't really any reserved words that end in "Root", but playing
// it safe and checking.
- return SanitizeNameForObjC(name, "_RootClass");
+ return SanitizeNameForObjC(name, "_RootClass", NULL);
}
string ClassNameWorker(const Descriptor* descriptor) {
@@ -372,11 +404,15 @@ string ClassNameWorker(const EnumDescriptor* descriptor) {
}
string ClassName(const Descriptor* descriptor) {
+ return ClassName(descriptor, NULL);
+}
+
+string ClassName(const Descriptor* descriptor, string* out_suffix_added) {
// 1. Message names are used as is (style calls for CamelCase, trust it).
// 2. Check for reserved word at the very end and then suffix things.
string prefix = FileClassPrefix(descriptor->file());
string name = ClassNameWorker(descriptor);
- return SanitizeNameForObjC(prefix + name, "_Class");
+ return SanitizeNameForObjC(prefix + name, "_Class", out_suffix_added);
}
string EnumName(const EnumDescriptor* descriptor) {
@@ -390,7 +426,7 @@ string EnumName(const EnumDescriptor* descriptor) {
// yields Fixed_Class, Fixed_Size.
string name = FileClassPrefix(descriptor->file());
name += ClassNameWorker(descriptor);
- return SanitizeNameForObjC(name, "_Enum");
+ return SanitizeNameForObjC(name, "_Enum", NULL);
}
string EnumValueName(const EnumValueDescriptor* descriptor) {
@@ -405,7 +441,7 @@ string EnumValueName(const EnumValueDescriptor* descriptor) {
const string& name = class_name + "_" + value_str;
// There aren't really any reserved words with an underscore and a leading
// capital letter, but playing it safe and checking.
- return SanitizeNameForObjC(name, "_Value");
+ return SanitizeNameForObjC(name, "_Value", NULL);
}
string EnumValueShortName(const EnumValueDescriptor* descriptor) {
@@ -442,7 +478,7 @@ string UnCamelCaseEnumShortName(const string& name) {
string ExtensionMethodName(const FieldDescriptor* descriptor) {
const string& name = NameFromFieldDescriptor(descriptor);
const string& result = UnderscoresToCamelCase(name, false);
- return SanitizeNameForObjC(result, "_Extension");
+ return SanitizeNameForObjC(result, "_Extension", NULL);
}
string FieldName(const FieldDescriptor* field) {
@@ -457,7 +493,7 @@ string FieldName(const FieldDescriptor* field) {
result += "_p";
}
}
- return SanitizeNameForObjC(result, "_p");
+ return SanitizeNameForObjC(result, "_p", NULL);
}
string FieldNameCapitalized(const FieldDescriptor* field) {
@@ -817,17 +853,21 @@ bool HasNonZeroDefaultValue(const FieldDescriptor* field) {
return false;
}
-string BuildFlagsString(const vector<string>& strings) {
+string BuildFlagsString(const FlagType flag_type,
+ const vector<string>& strings) {
if (strings.size() == 0) {
- return "0";
+ return GetZeroEnumNameForFlagType(flag_type);
+ } else if (strings.size() == 1) {
+ return strings[0];
}
- string string;
+ string string("(" + GetEnumNameForFlagType(flag_type) + ")(");
for (size_t i = 0; i != strings.size(); ++i) {
if (i > 0) {
string.append(" | ");
}
string.append(strings[i]);
}
+ string.append(")");
return string;
}
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
index b05983df..d17d44aa 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
@@ -67,6 +67,9 @@ bool IsRetainedName(const string& name);
// handling under ARC.
bool IsInitName(const string& name);
+// Gets the objc_class_prefix.
+string FileClassPrefix(const FileDescriptor* file);
+
// Gets the path of the file we're going to generate (sans the .pb.h
// extension). The path will be dependent on the objectivec package
// declared in the proto package.
@@ -83,6 +86,7 @@ string FileClassName(const FileDescriptor* file);
// These return the fully-qualified class name corresponding to the given
// descriptor.
string ClassName(const Descriptor* descriptor);
+string ClassName(const Descriptor* descriptor, string* out_suffix_added);
string EnumName(const EnumDescriptor* descriptor);
// Returns the fully-qualified name of the enum value corresponding to the
@@ -137,6 +141,12 @@ enum ObjectiveCType {
OBJECTIVECTYPE_MESSAGE
};
+enum FlagType {
+ FLAGTYPE_DESCRIPTOR_INITIALIZATION,
+ FLAGTYPE_EXTENSION,
+ FLAGTYPE_FIELD
+};
+
template<class TDescriptor>
string GetOptionalDeprecatedAttribute(const TDescriptor* descriptor, bool preSpace = true, bool postNewline = false) {
if (descriptor->options().deprecated()) {
@@ -168,7 +178,7 @@ string GPBGenericValueFieldName(const FieldDescriptor* field);
string DefaultValue(const FieldDescriptor* field);
bool HasNonZeroDefaultValue(const FieldDescriptor* field);
-string BuildFlagsString(const vector<string>& strings);
+string BuildFlagsString(const FlagType type, const vector<string>& strings);
// Builds HeaderDoc/appledoc style comments out of the comments in the .proto
// file.
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
index ac5d8aea..0bc9dc10 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
@@ -115,7 +115,7 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
if (value_field_flags.find("GPBFieldHasEnumDescriptor") != string::npos) {
field_flags.push_back("GPBFieldHasEnumDescriptor");
}
- variables_["fieldflags"] = BuildFlagsString(field_flags);
+ variables_["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags);
ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
const bool value_is_object_type =
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
index 822da893..4c6e1b55 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
@@ -521,7 +521,8 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
if (descriptor_->options().message_set_wire_format()) {
init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat");
}
- vars["init_flags"] = BuildFlagsString(init_flags);
+ vars["init_flags"] = BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION,
+ init_flags);
printer->Print(
vars,
@@ -579,6 +580,19 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
" [localDescriptor setupExtensionRanges:ranges\n"
" count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
}
+ if (descriptor_->containing_type() != NULL) {
+ string parent_class_name = ClassName(descriptor_->containing_type());
+ printer->Print(
+ " [localDescriptor setupContainingMessageClassName:GPBStringifySymbol($parent_name$)];\n",
+ "parent_name", parent_class_name);
+ }
+ string suffix_added;
+ ClassName(descriptor_, &suffix_added);
+ if (suffix_added.size() > 0) {
+ printer->Print(
+ " [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n",
+ "suffix", suffix_added);
+ }
printer->Print(
" NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
" descriptor = localDescriptor;\n"
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index 214d7c9c..519ed8fc 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -525,7 +525,6 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
SourceCodeInfo source_code_info;
source_code_info_ = &source_code_info;
- vector<string> top_doc_comments;
if (LookingAtType(io::Tokenizer::TYPE_START)) {
// Advance to first token.
input_->NextWithComments(NULL, &upcoming_detached_comments_,
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 0028c708..92c70c0d 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -2533,7 +2533,7 @@ void DescriptorProto_ExtensionRange::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -2836,7 +2836,7 @@ void DescriptorProto_ReservedRange::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -7347,7 +7347,7 @@ void MethodDescriptorProto::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -8163,7 +8163,7 @@ void FileOptions::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -9570,7 +9570,7 @@ void MessageOptions::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -10183,7 +10183,7 @@ void FieldOptions::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -11177,7 +11177,7 @@ void EnumOptions::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -13033,7 +13033,7 @@ void UninterpretedOption::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
@@ -14918,7 +14918,7 @@ void GeneratedCodeInfo_Annotation::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc
index 94ece18e..ed5cca4b 100644
--- a/src/google/protobuf/duration.pb.cc
+++ b/src/google/protobuf/duration.pb.cc
@@ -185,7 +185,7 @@ void Duration::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc
index 542e5ed7..487e62b0 100644
--- a/src/google/protobuf/timestamp.pb.cc
+++ b/src/google/protobuf/timestamp.pb.cc
@@ -199,7 +199,7 @@ void Timestamp::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc
index 7ba909ef..a2a7f282 100644
--- a/src/google/protobuf/type.pb.cc
+++ b/src/google/protobuf/type.pb.cc
@@ -1125,7 +1125,7 @@ void Field::Clear() {
#endif
#define ZR_(first, last) do {\
- ::memset(&first, 0,\
+ ::memset(&(first), 0,\
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc
index 1e8dab70..fa31f763 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.cc
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc
@@ -165,7 +165,10 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes(
if (current_ == NULL) {
ow_->RenderBytes(name, value);
} else {
- RenderDataPiece(name, DataPiece(value, false, true));
+ // Since StringPiece is essentially a pointer, takes a copy of "value" to
+ // avoid ownership issues.
+ string_values_.push_back(new string(value.ToString()));
+ RenderDataPiece(name, DataPiece(*string_values_.back(), false, true));
}
return this;
}
diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc
index dacac5e0..24ff5fd6 100644
--- a/src/google/protobuf/util/json_util_test.cc
+++ b/src/google/protobuf/util/json_util_test.cc
@@ -128,6 +128,34 @@ TEST_F(JsonUtilTest, TestDefaultValues) {
"\"repeatedMessageValue\":[]"
"}",
ToJson(m, options));
+
+ options.always_print_primitive_fields = true;
+ m.set_string_value("i am a test string value");
+ m.set_bytes_value("i am a test bytes value");
+ EXPECT_EQ(
+ "{\"boolValue\":false,"
+ "\"int32Value\":0,"
+ "\"int64Value\":\"0\","
+ "\"uint32Value\":0,"
+ "\"uint64Value\":\"0\","
+ "\"floatValue\":0,"
+ "\"doubleValue\":0,"
+ "\"stringValue\":\"i am a test string value\","
+ "\"bytesValue\":\"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=\","
+ "\"enumValue\":\"FOO\","
+ "\"repeatedBoolValue\":[],"
+ "\"repeatedInt32Value\":[],"
+ "\"repeatedInt64Value\":[],"
+ "\"repeatedUint32Value\":[],"
+ "\"repeatedUint64Value\":[],"
+ "\"repeatedFloatValue\":[],"
+ "\"repeatedDoubleValue\":[],"
+ "\"repeatedStringValue\":[],"
+ "\"repeatedBytesValue\":[],"
+ "\"repeatedEnumValue\":[],"
+ "\"repeatedMessageValue\":[]"
+ "}",
+ ToJson(m, options));
}
TEST_F(JsonUtilTest, ParseMessage) {