aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/descriptor.cc
diff options
context:
space:
mode:
authorGravatar Jisi Liu <jisi.liu@gmail.com>2015-10-05 11:59:43 -0700
committerGravatar Jisi Liu <jisi.liu@gmail.com>2015-10-05 11:59:43 -0700
commit46e8ff63cb67a6520711da5317aaaef04d0414d0 (patch)
tree64370726fe469f8dfca7b14f8b8cb80b6cc856f6 /src/google/protobuf/descriptor.cc
parent0087da9d4775f79c67362cc89c653f3a33a9bae2 (diff)
Down-integrate from google internal.
Diffstat (limited to 'src/google/protobuf/descriptor.cc')
-rw-r--r--src/google/protobuf/descriptor.cc91
1 files changed, 88 insertions, 3 deletions
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();