| Index: third_party/protobuf/src/google/protobuf/util/internal/default_value_objectwriter.cc
|
| diff --git a/third_party/protobuf/src/google/protobuf/util/internal/default_value_objectwriter.cc b/third_party/protobuf/src/google/protobuf/util/internal/default_value_objectwriter.cc
|
| index 21d7a2e4ab94da0b4e813f814511250ca440cbd2..1772219ab2a9f5f9c71e2c0c9551c866c015f505 100644
|
| --- a/third_party/protobuf/src/google/protobuf/util/internal/default_value_objectwriter.cc
|
| +++ b/third_party/protobuf/src/google/protobuf/util/internal/default_value_objectwriter.cc
|
| @@ -64,6 +64,7 @@ DefaultValueObjectWriter::DefaultValueObjectWriter(
|
| type_(type),
|
| current_(NULL),
|
| root_(NULL),
|
| + suppress_empty_list_(false),
|
| field_scrub_callback_(NULL),
|
| ow_(ow) {}
|
|
|
| @@ -164,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;
|
| }
|
| @@ -184,12 +188,10 @@ void DefaultValueObjectWriter::RegisterFieldScrubCallBack(
|
| field_scrub_callback_.reset(field_scrub_callback.release());
|
| }
|
|
|
| -DefaultValueObjectWriter::Node::Node(const string& name,
|
| - const google::protobuf::Type* type,
|
| - NodeKind kind, const DataPiece& data,
|
| - bool is_placeholder,
|
| - const vector<string>& path,
|
| - FieldScrubCallBack* field_scrub_callback)
|
| +DefaultValueObjectWriter::Node::Node(
|
| + const string& name, const google::protobuf::Type* type, NodeKind kind,
|
| + const DataPiece& data, bool is_placeholder, const std::vector<string>& path,
|
| + bool suppress_empty_list, FieldScrubCallBack* field_scrub_callback)
|
| : name_(name),
|
| type_(type),
|
| kind_(kind),
|
| @@ -197,6 +199,7 @@ DefaultValueObjectWriter::Node::Node(const string& name,
|
| data_(data),
|
| is_placeholder_(is_placeholder),
|
| path_(path),
|
| + suppress_empty_list_(suppress_empty_list),
|
| field_scrub_callback_(field_scrub_callback) {}
|
|
|
| DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild(
|
| @@ -230,6 +233,9 @@ void DefaultValueObjectWriter::Node::WriteTo(ObjectWriter* ow) {
|
| // Write out lists. If we didn't have any list in response, write out empty
|
| // list.
|
| if (kind_ == LIST) {
|
| + // Suppress empty lists if requested.
|
| + if (suppress_empty_list_ && is_placeholder_) return;
|
| +
|
| ow->StartList(name_);
|
| WriteChildren(ow);
|
| ow->EndList();
|
| @@ -304,7 +310,7 @@ void DefaultValueObjectWriter::Node::PopulateChildren(
|
|
|
| // This code is checking if the field to be added to the tree should be
|
| // scrubbed or not by calling the field_scrub_callback_ callback function.
|
| - vector<string> path;
|
| + std::vector<string> path;
|
| if (!path_.empty()) {
|
| path.insert(path.begin(), path_.begin(), path_.end());
|
| }
|
| @@ -366,7 +372,7 @@ void DefaultValueObjectWriter::Node::PopulateChildren(
|
| field.json_name(), field_type, kind,
|
| kind == PRIMITIVE ? CreateDefaultDataPieceForField(field, typeinfo)
|
| : DataPiece::NullData(),
|
| - true, path, field_scrub_callback_));
|
| + true, path, suppress_empty_list_, field_scrub_callback_));
|
| new_children.push_back(child.release());
|
| }
|
| // Adds all leftover nodes in children_ to the beginning of new_child.
|
| @@ -460,9 +466,10 @@ DataPiece DefaultValueObjectWriter::CreateDefaultDataPieceForField(
|
| DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
|
| StringPiece name) {
|
| if (current_ == NULL) {
|
| - vector<string> path;
|
| + std::vector<string> path;
|
| root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(),
|
| - false, path, field_scrub_callback_.get()));
|
| + false, path, suppress_empty_list_,
|
| + field_scrub_callback_.get()));
|
| root_->PopulateChildren(typeinfo_);
|
| current_ = root_.get();
|
| return this;
|
| @@ -478,7 +485,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
|
| : NULL),
|
| OBJECT, DataPiece::NullData(), false,
|
| child == NULL ? current_->path() : child->path(),
|
| - field_scrub_callback_.get()));
|
| + suppress_empty_list_, field_scrub_callback_.get()));
|
| child = node.get();
|
| current_->AddChild(node.release());
|
| }
|
| @@ -507,9 +514,10 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::EndObject() {
|
| DefaultValueObjectWriter* DefaultValueObjectWriter::StartList(
|
| StringPiece name) {
|
| if (current_ == NULL) {
|
| - vector<string> path;
|
| + std::vector<string> path;
|
| root_.reset(new Node(name.ToString(), &type_, LIST, DataPiece::NullData(),
|
| - false, path, field_scrub_callback_.get()));
|
| + false, path, suppress_empty_list_,
|
| + field_scrub_callback_.get()));
|
| current_ = root_.get();
|
| return this;
|
| }
|
| @@ -519,7 +527,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartList(
|
| google::protobuf::scoped_ptr<Node> node(
|
| new Node(name.ToString(), NULL, LIST, DataPiece::NullData(), false,
|
| child == NULL ? current_->path() : child->path(),
|
| - field_scrub_callback_.get()));
|
| + suppress_empty_list_, field_scrub_callback_.get()));
|
| child = node.get();
|
| current_->AddChild(node.release());
|
| }
|
| @@ -549,26 +557,29 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::EndList() {
|
| void DefaultValueObjectWriter::RenderDataPiece(StringPiece name,
|
| const DataPiece& data) {
|
| MaybePopulateChildrenOfAny(current_);
|
| - util::StatusOr<string> data_string = data.ToString();
|
| if (current_->type() != NULL && current_->type()->name() == kAnyType &&
|
| - name == "@type" && data_string.ok()) {
|
| - const string& string_value = data_string.ValueOrDie();
|
| - // If the type of current_ is "Any" and its "@type" field is being set here,
|
| - // sets the type of current_ to be the type specified by the "@type".
|
| - util::StatusOr<const google::protobuf::Type*> found_type =
|
| - typeinfo_->ResolveTypeUrl(string_value);
|
| - if (!found_type.ok()) {
|
| - GOOGLE_LOG(WARNING) << "Failed to resolve type '" << string_value << "'.";
|
| - } else {
|
| - current_->set_type(found_type.ValueOrDie());
|
| - }
|
| - current_->set_is_any(true);
|
| - // If the "@type" field is placed after other fields, we should populate
|
| - // other children of primitive type now. Otherwise, we should wait until the
|
| - // first value field is rendered before we populate the children, because
|
| - // the "value" field of a Any message could be omitted.
|
| - if (current_->number_of_children() > 1 && current_->type() != NULL) {
|
| - current_->PopulateChildren(typeinfo_);
|
| + name == "@type") {
|
| + util::StatusOr<string> data_string = data.ToString();
|
| + if (data_string.ok()) {
|
| + const string& string_value = data_string.ValueOrDie();
|
| + // If the type of current_ is "Any" and its "@type" field is being set
|
| + // here, sets the type of current_ to be the type specified by the
|
| + // "@type".
|
| + util::StatusOr<const google::protobuf::Type*> found_type =
|
| + typeinfo_->ResolveTypeUrl(string_value);
|
| + if (!found_type.ok()) {
|
| + GOOGLE_LOG(WARNING) << "Failed to resolve type '" << string_value << "'.";
|
| + } else {
|
| + current_->set_type(found_type.ValueOrDie());
|
| + }
|
| + current_->set_is_any(true);
|
| + // If the "@type" field is placed after other fields, we should populate
|
| + // other children of primitive type now. Otherwise, we should wait until
|
| + // the first value field is rendered before we populate the children,
|
| + // because the "value" field of a Any message could be omitted.
|
| + if (current_->number_of_children() > 1 && current_->type() != NULL) {
|
| + current_->PopulateChildren(typeinfo_);
|
| + }
|
| }
|
| }
|
| Node* child = current_->FindChild(name);
|
| @@ -577,8 +588,7 @@ void DefaultValueObjectWriter::RenderDataPiece(StringPiece name,
|
| google::protobuf::scoped_ptr<Node> node(
|
| new Node(name.ToString(), NULL, PRIMITIVE, data, false,
|
| child == NULL ? current_->path() : child->path(),
|
| - field_scrub_callback_.get()));
|
| - child = node.get();
|
| + suppress_empty_list_, field_scrub_callback_.get()));
|
| current_->AddChild(node.release());
|
| } else {
|
| child->set_data(data);
|
|
|