| Index: third_party/protobuf/src/google/protobuf/util/field_mask_util.cc
|
| diff --git a/third_party/protobuf/src/google/protobuf/util/field_mask_util.cc b/third_party/protobuf/src/google/protobuf/util/field_mask_util.cc
|
| index 547c9fb528469d76fb2dd3db79e3e7499e1df043..07550e6d764a63484eaf61042f56babfbc4bc86d 100644
|
| --- a/third_party/protobuf/src/google/protobuf/util/field_mask_util.cc
|
| +++ b/third_party/protobuf/src/google/protobuf/util/field_mask_util.cc
|
| @@ -45,7 +45,7 @@ string FieldMaskUtil::ToString(const FieldMask& mask) {
|
|
|
| void FieldMaskUtil::FromString(StringPiece str, FieldMask* out) {
|
| out->Clear();
|
| - vector<string> paths = Split(str, ",");
|
| + std::vector<string> paths = Split(str, ",");
|
| for (int i = 0; i < paths.size(); ++i) {
|
| if (paths[i].empty()) continue;
|
| out->add_paths(paths[i]);
|
| @@ -116,7 +116,7 @@ bool FieldMaskUtil::ToJsonString(const FieldMask& mask, string* out) {
|
|
|
| bool FieldMaskUtil::FromJsonString(StringPiece str, FieldMask* out) {
|
| out->Clear();
|
| - vector<string> paths = Split(str, ",");
|
| + std::vector<string> paths = Split(str, ",");
|
| for (int i = 0; i < paths.size(); ++i) {
|
| if (paths[i].empty()) continue;
|
| string snakecase_path;
|
| @@ -128,9 +128,13 @@ bool FieldMaskUtil::FromJsonString(StringPiece str, FieldMask* out) {
|
| return true;
|
| }
|
|
|
| -bool FieldMaskUtil::InternalIsValidPath(const Descriptor* descriptor,
|
| - StringPiece path) {
|
| - vector<string> parts = Split(path, ".");
|
| +bool FieldMaskUtil::GetFieldDescriptors(
|
| + const Descriptor* descriptor, StringPiece path,
|
| + std::vector<const FieldDescriptor*>* field_descriptors) {
|
| + if (field_descriptors != NULL) {
|
| + field_descriptors->clear();
|
| + }
|
| + std::vector<string> parts = Split(path, ".");
|
| for (int i = 0; i < parts.size(); ++i) {
|
| const string& field_name = parts[i];
|
| if (descriptor == NULL) {
|
| @@ -140,6 +144,9 @@ bool FieldMaskUtil::InternalIsValidPath(const Descriptor* descriptor,
|
| if (field == NULL) {
|
| return false;
|
| }
|
| + if (field_descriptors != NULL) {
|
| + field_descriptors->push_back(field);
|
| + }
|
| if (!field->is_repeated() &&
|
| field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
| descriptor = field->message_type();
|
| @@ -200,6 +207,15 @@ class FieldMaskTree {
|
| MergeMessage(&root_, source, options, destination);
|
| }
|
|
|
| + // Trims all fields not specified by this tree from the given message.
|
| + void TrimMessage(Message* message) {
|
| + // Do nothing if the tree is empty.
|
| + if (root_.children.empty()) {
|
| + return;
|
| + }
|
| + TrimMessage(&root_, message);
|
| + }
|
| +
|
| private:
|
| struct Node {
|
| Node() {}
|
| @@ -207,14 +223,14 @@ class FieldMaskTree {
|
| ~Node() { ClearChildren(); }
|
|
|
| void ClearChildren() {
|
| - for (map<string, Node*>::iterator it = children.begin();
|
| + for (std::map<string, Node*>::iterator it = children.begin();
|
| it != children.end(); ++it) {
|
| delete it->second;
|
| }
|
| children.clear();
|
| }
|
|
|
| - map<string, Node*> children;
|
| + std::map<string, Node*> children;
|
|
|
| private:
|
| GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node);
|
| @@ -233,6 +249,9 @@ class FieldMaskTree {
|
| const FieldMaskUtil::MergeOptions& options,
|
| Message* destination);
|
|
|
| + // Trims all fields not specified by this sub-tree from the given message.
|
| + void TrimMessage(const Node* node, Message* message);
|
| +
|
| Node root_;
|
|
|
| GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldMaskTree);
|
| @@ -262,7 +281,7 @@ void FieldMaskTree::MergeToFieldMask(const string& prefix, const Node* node,
|
| out->add_paths(prefix);
|
| return;
|
| }
|
| - for (map<string, Node*>::const_iterator it = node->children.begin();
|
| + for (std::map<string, Node*>::const_iterator it = node->children.begin();
|
| it != node->children.end(); ++it) {
|
| string current_path = prefix.empty() ? it->first : prefix + "." + it->first;
|
| MergeToFieldMask(current_path, it->second, out);
|
| @@ -270,7 +289,7 @@ void FieldMaskTree::MergeToFieldMask(const string& prefix, const Node* node,
|
| }
|
|
|
| void FieldMaskTree::AddPath(const string& path) {
|
| - vector<string> parts = Split(path, ".");
|
| + std::vector<string> parts = Split(path, ".");
|
| if (parts.empty()) {
|
| return;
|
| }
|
| @@ -297,7 +316,7 @@ void FieldMaskTree::AddPath(const string& path) {
|
| }
|
|
|
| void FieldMaskTree::IntersectPath(const string& path, FieldMaskTree* out) {
|
| - vector<string> parts = Split(path, ".");
|
| + std::vector<string> parts = Split(path, ".");
|
| if (parts.empty()) {
|
| return;
|
| }
|
| @@ -327,7 +346,7 @@ void FieldMaskTree::MergeLeafNodesToTree(const string& prefix, const Node* node,
|
| if (node->children.empty()) {
|
| out->AddPath(prefix);
|
| }
|
| - for (map<string, Node*>::const_iterator it = node->children.begin();
|
| + for (std::map<string, Node*>::const_iterator it = node->children.begin();
|
| it != node->children.end(); ++it) {
|
| string current_path = prefix.empty() ? it->first : prefix + "." + it->first;
|
| MergeLeafNodesToTree(current_path, it->second, out);
|
| @@ -341,7 +360,7 @@ void FieldMaskTree::MergeMessage(const Node* node, const Message& source,
|
| const Reflection* source_reflection = source.GetReflection();
|
| const Reflection* destination_reflection = destination->GetReflection();
|
| const Descriptor* descriptor = source.GetDescriptor();
|
| - for (map<string, Node*>::const_iterator it = node->children.begin();
|
| + for (std::map<string, Node*>::const_iterator it = node->children.begin();
|
| it != node->children.end(); ++it) {
|
| const string& field_name = it->first;
|
| const Node* child = it->second;
|
| @@ -367,11 +386,15 @@ void FieldMaskTree::MergeMessage(const Node* node, const Message& source,
|
| }
|
| if (!field->is_repeated()) {
|
| switch (field->cpp_type()) {
|
| -#define COPY_VALUE(TYPE, Name) \
|
| - case FieldDescriptor::CPPTYPE_##TYPE: { \
|
| - destination_reflection->Set##Name( \
|
| - destination, field, source_reflection->Get##Name(source, field)); \
|
| - break; \
|
| +#define COPY_VALUE(TYPE, Name) \
|
| + case FieldDescriptor::CPPTYPE_##TYPE: { \
|
| + if (source_reflection->HasField(source, field)) { \
|
| + destination_reflection->Set##Name( \
|
| + destination, field, source_reflection->Get##Name(source, field)); \
|
| + } else { \
|
| + destination_reflection->ClearField(destination, field); \
|
| + } \
|
| + break; \
|
| }
|
| COPY_VALUE(BOOL, Bool)
|
| COPY_VALUE(INT32, Int32)
|
| @@ -433,6 +456,27 @@ void FieldMaskTree::MergeMessage(const Node* node, const Message& source,
|
| }
|
| }
|
|
|
| +void FieldMaskTree::TrimMessage(const Node* node, Message* message) {
|
| + GOOGLE_DCHECK(!node->children.empty());
|
| + const Reflection* reflection = message->GetReflection();
|
| + const Descriptor* descriptor = message->GetDescriptor();
|
| + const int32 field_count = descriptor->field_count();
|
| + for (int index = 0; index < field_count; ++index) {
|
| + const FieldDescriptor* field = descriptor->field(index);
|
| + map<string, Node*>::const_iterator it = node->children.find(field->name());
|
| + if (it == node->children.end()) {
|
| + reflection->ClearField(message, field);
|
| + } else {
|
| + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
| + Node* child = it->second;
|
| + if (!child->children.empty()) {
|
| + TrimMessage(child, reflection->MutableMessage(message, field));
|
| + }
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| } // namespace
|
|
|
| void FieldMaskUtil::ToCanonicalForm(const FieldMask& mask, FieldMask* out) {
|
| @@ -489,6 +533,14 @@ void FieldMaskUtil::MergeMessageTo(const Message& source, const FieldMask& mask,
|
| tree.MergeMessage(source, options, destination);
|
| }
|
|
|
| +void FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* destination) {
|
| + // Build a FieldMaskTree and walk through the tree to merge all specified
|
| + // fields.
|
| + FieldMaskTree tree;
|
| + tree.MergeFromFieldMask(mask);
|
| + tree.TrimMessage(GOOGLE_CHECK_NOTNULL(destination));
|
| +}
|
| +
|
| } // namespace util
|
| } // namespace protobuf
|
| } // namespace google
|
|
|