diff options
Diffstat (limited to 'src/google/protobuf/util/field_mask_util.cc')
-rw-r--r-- | src/google/protobuf/util/field_mask_util.cc | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/src/google/protobuf/util/field_mask_util.cc b/src/google/protobuf/util/field_mask_util.cc index a2e2a388..cf65ef27 100644 --- a/src/google/protobuf/util/field_mask_util.cc +++ b/src/google/protobuf/util/field_mask_util.cc @@ -53,7 +53,8 @@ void FieldMaskUtil::FromString(StringPiece str, FieldMask* out) { } } -bool FieldMaskUtil::SnakeCaseToCamelCase(StringPiece input, string* output) { +bool FieldMaskUtil::SnakeCaseToCamelCase(StringPiece input, + string* output) { output->clear(); bool after_underscore = false; for (int i = 0; i < input.size(); ++i) { @@ -82,7 +83,8 @@ bool FieldMaskUtil::SnakeCaseToCamelCase(StringPiece input, string* output) { return true; } -bool FieldMaskUtil::CamelCaseToSnakeCase(StringPiece input, string* output) { +bool FieldMaskUtil::CamelCaseToSnakeCase(StringPiece input, + string* output) { output->clear(); for (int i = 0; i < input.size(); ++i) { if (input[i] == '_') { @@ -228,12 +230,13 @@ class FieldMaskTree { } // Trims all fields not specified by this tree from the given message. - void TrimMessage(Message* message) { + // Returns true if the message is modified. + bool TrimMessage(Message* message) { // Do nothing if the tree is empty. if (root_.children.empty()) { - return; + return false; } - TrimMessage(&root_, message); + return TrimMessage(&root_, message); } private: @@ -276,7 +279,8 @@ class FieldMaskTree { void AddRequiredFieldPath(Node* node, const Descriptor* descriptor); // Trims all fields not specified by this sub-tree from the given message. - void TrimMessage(const Node* node, Message* message); + // Returns true if the message is actually modified + bool TrimMessage(const Node* node, Message* message); Node root_; @@ -576,26 +580,39 @@ void FieldMaskTree::AddRequiredFieldPath( } } -void FieldMaskTree::TrimMessage(const Node* node, Message* message) { +bool 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(); + bool modified = false; for (int index = 0; index < field_count; ++index) { const FieldDescriptor* field = descriptor->field(index); std::map<string, Node*>::const_iterator it = node->children.find(field->name()); if (it == node->children.end()) { + if (field->is_repeated()) { + if (reflection->FieldSize(*message, field) != 0) { + modified = true; + } + } else { + if (reflection->HasField(*message, field)) { + modified = true; + } + } reflection->ClearField(message, field); } else { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { Node* child = it->second; if (!child->children.empty() && reflection->HasField(*message, field)) { - TrimMessage(child, reflection->MutableMessage(message, field)); + bool nestedMessageChanged = + TrimMessage(child, reflection->MutableMessage(message, field)); + modified = nestedMessageChanged || modified; } } } } + return modified; } } // namespace @@ -643,7 +660,8 @@ void FieldMaskUtil::InternalSubtract(const Descriptor* descriptor, tree.MergeToFieldMask(out); } -bool FieldMaskUtil::IsPathInFieldMask(StringPiece 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) { @@ -670,15 +688,15 @@ void FieldMaskUtil::MergeMessageTo(const Message& source, const FieldMask& mask, tree.MergeMessage(source, options, destination); } -void FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* destination) { +bool FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* message) { // Build a FieldMaskTree and walk through the tree to merge all specified // fields. FieldMaskTree tree; tree.MergeFromFieldMask(mask); - tree.TrimMessage(GOOGLE_CHECK_NOTNULL(destination)); + return tree.TrimMessage(GOOGLE_CHECK_NOTNULL(message)); } -void FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* destination, +bool FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* message, const TrimOptions& options) { // Build a FieldMaskTree and walk through the tree to merge all specified // fields. @@ -687,9 +705,9 @@ void FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* destination, // If keep_required_fields is true, implicitely add required fields of // a message present in the tree to prevent from trimming. if (options.keep_required_fields()) { - tree.AddRequiredFieldPath(GOOGLE_CHECK_NOTNULL(destination->GetDescriptor())); + tree.AddRequiredFieldPath(GOOGLE_CHECK_NOTNULL(message->GetDescriptor())); } - tree.TrimMessage(GOOGLE_CHECK_NOTNULL(destination)); + return tree.TrimMessage(GOOGLE_CHECK_NOTNULL(message)); } } // namespace util |