| 1 | // Protocol Buffers - Google's data interchange format | 
| 2 | // Copyright 2008 Google Inc.  All rights reserved. | 
| 3 | // https://developers.google.com/protocol-buffers/ | 
| 4 | // | 
| 5 | // Redistribution and use in source and binary forms, with or without | 
| 6 | // modification, are permitted provided that the following conditions are | 
| 7 | // met: | 
| 8 | // | 
| 9 | //     * Redistributions of source code must retain the above copyright | 
| 10 | // notice, this list of conditions and the following disclaimer. | 
| 11 | //     * Redistributions in binary form must reproduce the above | 
| 12 | // copyright notice, this list of conditions and the following disclaimer | 
| 13 | // in the documentation and/or other materials provided with the | 
| 14 | // distribution. | 
| 15 | //     * Neither the name of Google Inc. nor the names of its | 
| 16 | // contributors may be used to endorse or promote products derived from | 
| 17 | // this software without specific prior written permission. | 
| 18 | // | 
| 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
| 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
| 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
| 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
| 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
| 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
| 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
| 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
| 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
| 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
| 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 30 |  | 
| 31 | #include <google/protobuf/util/field_mask_util.h> | 
| 32 |  | 
| 33 | #include <cstdint> | 
| 34 |  | 
| 35 | #include <google/protobuf/stubs/strutil.h> | 
| 36 | #include <google/protobuf/message.h> | 
| 37 | #include <google/protobuf/stubs/map_util.h> | 
| 38 |  | 
| 39 | // Must be included last. | 
| 40 | #include <google/protobuf/port_def.inc> | 
| 41 |  | 
| 42 | namespace google { | 
| 43 | namespace protobuf { | 
| 44 | namespace util { | 
| 45 |  | 
| 46 | using google::protobuf::FieldMask; | 
| 47 |  | 
| 48 | std::string FieldMaskUtil::ToString(const FieldMask& mask) { | 
| 49 |   return Join(components: mask.paths(), delim: "," ); | 
| 50 | } | 
| 51 |  | 
| 52 | void FieldMaskUtil::FromString(StringPiece str, FieldMask* out) { | 
| 53 |   out->Clear(); | 
| 54 |   std::vector<std::string> paths = Split(full: str, delim: "," ); | 
| 55 |   for (const std::string& path : paths) { | 
| 56 |     if (path.empty()) continue; | 
| 57 |     out->add_paths(value: path); | 
| 58 |   } | 
| 59 | } | 
| 60 |  | 
| 61 | bool FieldMaskUtil::SnakeCaseToCamelCase(StringPiece input, | 
| 62 |                                          std::string* output) { | 
| 63 |   output->clear(); | 
| 64 |   bool after_underscore = false; | 
| 65 |   for (char input_char : input) { | 
| 66 |     if (input_char >= 'A' && input_char <= 'Z') { | 
| 67 |       // The field name must not contain uppercase letters. | 
| 68 |       return false; | 
| 69 |     } | 
| 70 |     if (after_underscore) { | 
| 71 |       if (input_char >= 'a' && input_char <= 'z') { | 
| 72 |         output->push_back(c: input_char + 'A' - 'a'); | 
| 73 |         after_underscore = false; | 
| 74 |       } else { | 
| 75 |         // The character after a "_" must be a lowercase letter. | 
| 76 |         return false; | 
| 77 |       } | 
| 78 |     } else if (input_char == '_') { | 
| 79 |       after_underscore = true; | 
| 80 |     } else { | 
| 81 |       output->push_back(c: input_char); | 
| 82 |     } | 
| 83 |   } | 
| 84 |   if (after_underscore) { | 
| 85 |     // Trailing "_". | 
| 86 |     return false; | 
| 87 |   } | 
| 88 |   return true; | 
| 89 | } | 
| 90 |  | 
| 91 | bool FieldMaskUtil::CamelCaseToSnakeCase(StringPiece input, | 
| 92 |                                          std::string* output) { | 
| 93 |   output->clear(); | 
| 94 |   for (const char c : input) { | 
| 95 |     if (c == '_') { | 
| 96 |       // The field name must not contain "_"s. | 
| 97 |       return false; | 
| 98 |     } | 
| 99 |     if (c >= 'A' && c <= 'Z') { | 
| 100 |       output->push_back(c: '_'); | 
| 101 |       output->push_back(c: c + 'a' - 'A'); | 
| 102 |     } else { | 
| 103 |       output->push_back(c: c); | 
| 104 |     } | 
| 105 |   } | 
| 106 |   return true; | 
| 107 | } | 
| 108 |  | 
| 109 | bool FieldMaskUtil::ToJsonString(const FieldMask& mask, std::string* out) { | 
| 110 |   out->clear(); | 
| 111 |   for (int i = 0; i < mask.paths_size(); ++i) { | 
| 112 |     const std::string& path = mask.paths(index: i); | 
| 113 |     std::string camelcase_path; | 
| 114 |     if (!SnakeCaseToCamelCase(input: path, output: &camelcase_path)) { | 
| 115 |       return false; | 
| 116 |     } | 
| 117 |     if (i > 0) { | 
| 118 |       out->push_back(c: ','); | 
| 119 |     } | 
| 120 |     out->append(str: camelcase_path); | 
| 121 |   } | 
| 122 |   return true; | 
| 123 | } | 
| 124 |  | 
| 125 | bool FieldMaskUtil::FromJsonString(StringPiece str, FieldMask* out) { | 
| 126 |   out->Clear(); | 
| 127 |   std::vector<std::string> paths = Split(full: str, delim: "," ); | 
| 128 |   for (const std::string& path : paths) { | 
| 129 |     if (path.empty()) continue; | 
| 130 |     std::string snakecase_path; | 
| 131 |     if (!CamelCaseToSnakeCase(input: path, output: &snakecase_path)) { | 
| 132 |       return false; | 
| 133 |     } | 
| 134 |     out->add_paths(value: snakecase_path); | 
| 135 |   } | 
| 136 |   return true; | 
| 137 | } | 
| 138 |  | 
| 139 | bool FieldMaskUtil::GetFieldDescriptors( | 
| 140 |     const Descriptor* descriptor, StringPiece path, | 
| 141 |     std::vector<const FieldDescriptor*>* field_descriptors) { | 
| 142 |   if (field_descriptors != nullptr) { | 
| 143 |     field_descriptors->clear(); | 
| 144 |   } | 
| 145 |   std::vector<std::string> parts = Split(full: path, delim: "." ); | 
| 146 |   for (const std::string& field_name : parts) { | 
| 147 |     if (descriptor == nullptr) { | 
| 148 |       return false; | 
| 149 |     } | 
| 150 |     const FieldDescriptor* field = descriptor->FindFieldByName(name: field_name); | 
| 151 |     if (field == nullptr) { | 
| 152 |       return false; | 
| 153 |     } | 
| 154 |     if (field_descriptors != nullptr) { | 
| 155 |       field_descriptors->push_back(x: field); | 
| 156 |     } | 
| 157 |     if (!field->is_repeated() && | 
| 158 |         field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { | 
| 159 |       descriptor = field->message_type(); | 
| 160 |     } else { | 
| 161 |       descriptor = nullptr; | 
| 162 |     } | 
| 163 |   } | 
| 164 |   return true; | 
| 165 | } | 
| 166 |  | 
| 167 | void FieldMaskUtil::GetFieldMaskForAllFields(const Descriptor* descriptor, | 
| 168 |                                              FieldMask* out) { | 
| 169 |   for (int i = 0; i < descriptor->field_count(); ++i) { | 
| 170 |     out->add_paths(value: descriptor->field(index: i)->name()); | 
| 171 |   } | 
| 172 | } | 
| 173 |  | 
| 174 | namespace { | 
| 175 | // A FieldMaskTree represents a FieldMask in a tree structure. For example, | 
| 176 | // given a FieldMask "foo.bar,foo.baz,bar.baz", the FieldMaskTree will be: | 
| 177 | // | 
| 178 | //   [root] -+- foo -+- bar | 
| 179 | //           |       | | 
| 180 | //           |       +- baz | 
| 181 | //           | | 
| 182 | //           +- bar --- baz | 
| 183 | // | 
| 184 | // In the tree, each leaf node represents a field path. | 
| 185 | class FieldMaskTree { | 
| 186 |  public: | 
| 187 |   FieldMaskTree(); | 
| 188 |   ~FieldMaskTree(); | 
| 189 |  | 
| 190 |   void MergeFromFieldMask(const FieldMask& mask); | 
| 191 |   void MergeToFieldMask(FieldMask* mask); | 
| 192 |  | 
| 193 |   // Add a field path into the tree. In a FieldMask, each field path matches | 
| 194 |   // the specified field and also all its sub-fields. If the field path to | 
| 195 |   // add is a sub-path of an existing field path in the tree (i.e., a leaf | 
| 196 |   // node), it means the tree already matches the given path so nothing will | 
| 197 |   // be added to the tree. If the path matches an existing non-leaf node in the | 
| 198 |   // tree, that non-leaf node will be turned into a leaf node with all its | 
| 199 |   // children removed because the path matches all the node's children. | 
| 200 |   void AddPath(const std::string& path); | 
| 201 |  | 
| 202 |   // Remove a path from the tree. | 
| 203 |   // If the path is a sub-path of an existing field path in the tree, it means | 
| 204 |   // we need remove the existing field path and add all sub-paths except | 
| 205 |   // specified path. If the path matches an existing node in the tree, this node | 
| 206 |   // will be moved. | 
| 207 |   void RemovePath(const std::string& path, const Descriptor* descriptor); | 
| 208 |  | 
| 209 |   // Calculate the intersection part of a field path with this tree and add | 
| 210 |   // the intersection field path into out. | 
| 211 |   void IntersectPath(const std::string& path, FieldMaskTree* out); | 
| 212 |  | 
| 213 |   // Merge all fields specified by this tree from one message to another. | 
| 214 |   void MergeMessage(const Message& source, | 
| 215 |                     const FieldMaskUtil::MergeOptions& options, | 
| 216 |                     Message* destination) { | 
| 217 |     // Do nothing if the tree is empty. | 
| 218 |     if (root_.children.empty()) { | 
| 219 |       return; | 
| 220 |     } | 
| 221 |     MergeMessage(node: &root_, source, options, destination); | 
| 222 |   } | 
| 223 |  | 
| 224 |   // Add required field path of the message to this tree based on current tree | 
| 225 |   // structure. If a message is present in the tree, add the path of its | 
| 226 |   // required field to the tree. This is to make sure that after trimming a | 
| 227 |   // message with required fields are set, check IsInitialized() will not fail. | 
| 228 |   void AddRequiredFieldPath(const Descriptor* descriptor) { | 
| 229 |     // Do nothing if the tree is empty. | 
| 230 |     if (root_.children.empty()) { | 
| 231 |       return; | 
| 232 |     } | 
| 233 |     AddRequiredFieldPath(node: &root_, descriptor); | 
| 234 |   } | 
| 235 |  | 
| 236 |   // Trims all fields not specified by this tree from the given message. | 
| 237 |   // Returns true if the message is modified. | 
| 238 |   bool TrimMessage(Message* message) { | 
| 239 |     // Do nothing if the tree is empty. | 
| 240 |     if (root_.children.empty()) { | 
| 241 |       return false; | 
| 242 |     } | 
| 243 |     return TrimMessage(node: &root_, message); | 
| 244 |   } | 
| 245 |  | 
| 246 |  private: | 
| 247 |   struct Node { | 
| 248 |     Node() {} | 
| 249 |  | 
| 250 |     ~Node() { ClearChildren(); } | 
| 251 |  | 
| 252 |     void ClearChildren() { | 
| 253 |       for (std::map<std::string, Node*>::iterator it = children.begin(); | 
| 254 |            it != children.end(); ++it) { | 
| 255 |         delete it->second; | 
| 256 |       } | 
| 257 |       children.clear(); | 
| 258 |     } | 
| 259 |  | 
| 260 |     std::map<std::string, Node*> children; | 
| 261 |  | 
| 262 |    private: | 
| 263 |     GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node); | 
| 264 |   }; | 
| 265 |  | 
| 266 |   // Merge a sub-tree to mask. This method adds the field paths represented | 
| 267 |   // by all leaf nodes descended from "node" to mask. | 
| 268 |   void MergeToFieldMask(const std::string& prefix, const Node* node, | 
| 269 |                         FieldMask* out); | 
| 270 |  | 
| 271 |   // Merge all leaf nodes of a sub-tree to another tree. | 
| 272 |   void MergeLeafNodesToTree(const std::string& prefix, const Node* node, | 
| 273 |                             FieldMaskTree* out); | 
| 274 |  | 
| 275 |   // Merge all fields specified by a sub-tree from one message to another. | 
| 276 |   void MergeMessage(const Node* node, const Message& source, | 
| 277 |                     const FieldMaskUtil::MergeOptions& options, | 
| 278 |                     Message* destination); | 
| 279 |  | 
| 280 |   // Add required field path of the message to this tree based on current tree | 
| 281 |   // structure. If a message is present in the tree, add the path of its | 
| 282 |   // required field to the tree. This is to make sure that after trimming a | 
| 283 |   // message with required fields are set, check IsInitialized() will not fail. | 
| 284 |   void AddRequiredFieldPath(Node* node, const Descriptor* descriptor); | 
| 285 |  | 
| 286 |   // Trims all fields not specified by this sub-tree from the given message. | 
| 287 |   // Returns true if the message is actually modified | 
| 288 |   bool TrimMessage(const Node* node, Message* message); | 
| 289 |  | 
| 290 |   Node root_; | 
| 291 |  | 
| 292 |   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldMaskTree); | 
| 293 | }; | 
| 294 |  | 
| 295 | FieldMaskTree::FieldMaskTree() {} | 
| 296 |  | 
| 297 | FieldMaskTree::~FieldMaskTree() {} | 
| 298 |  | 
| 299 | void FieldMaskTree::MergeFromFieldMask(const FieldMask& mask) { | 
| 300 |   for (int i = 0; i < mask.paths_size(); ++i) { | 
| 301 |     AddPath(path: mask.paths(index: i)); | 
| 302 |   } | 
| 303 | } | 
| 304 |  | 
| 305 | void FieldMaskTree::MergeToFieldMask(FieldMask* mask) { | 
| 306 |   MergeToFieldMask(prefix: "" , node: &root_, out: mask); | 
| 307 | } | 
| 308 |  | 
| 309 | void FieldMaskTree::MergeToFieldMask(const std::string& prefix, | 
| 310 |                                      const Node* node, FieldMask* out) { | 
| 311 |   if (node->children.empty()) { | 
| 312 |     if (prefix.empty()) { | 
| 313 |       // This is the root node. | 
| 314 |       return; | 
| 315 |     } | 
| 316 |     out->add_paths(value: prefix); | 
| 317 |     return; | 
| 318 |   } | 
| 319 |   for (std::map<std::string, Node*>::const_iterator it = node->children.begin(); | 
| 320 |        it != node->children.end(); ++it) { | 
| 321 |     std::string current_path = | 
| 322 |         prefix.empty() ? it->first : prefix + "."  + it->first; | 
| 323 |     MergeToFieldMask(prefix: current_path, node: it->second, out); | 
| 324 |   } | 
| 325 | } | 
| 326 |  | 
| 327 | void FieldMaskTree::AddPath(const std::string& path) { | 
| 328 |   std::vector<std::string> parts = Split(full: path, delim: "." ); | 
| 329 |   if (parts.empty()) { | 
| 330 |     return; | 
| 331 |   } | 
| 332 |   bool new_branch = false; | 
| 333 |   Node* node = &root_; | 
| 334 |   for (const std::string& node_name : parts) { | 
| 335 |     if (!new_branch && node != &root_ && node->children.empty()) { | 
| 336 |       // Path matches an existing leaf node. This means the path is already | 
| 337 |       // covered by this tree (for example, adding "foo.bar.baz" to a tree | 
| 338 |       // which already contains "foo.bar"). | 
| 339 |       return; | 
| 340 |     } | 
| 341 |     Node*& child = node->children[node_name]; | 
| 342 |     if (child == nullptr) { | 
| 343 |       new_branch = true; | 
| 344 |       child = new Node(); | 
| 345 |     } | 
| 346 |     node = child; | 
| 347 |   } | 
| 348 |   if (!node->children.empty()) { | 
| 349 |     node->ClearChildren(); | 
| 350 |   } | 
| 351 | } | 
| 352 |  | 
| 353 | void FieldMaskTree::RemovePath(const std::string& path, | 
| 354 |                                const Descriptor* descriptor) { | 
| 355 |   if (root_.children.empty()) { | 
| 356 |     // Nothing to be removed from an empty tree. We shortcut it here so an empty | 
| 357 |     // tree won't be interpreted as a field mask containing all fields by the | 
| 358 |     // code below. | 
| 359 |     return; | 
| 360 |   } | 
| 361 |   std::vector<std::string> parts = Split(full: path, delim: "." ); | 
| 362 |   if (parts.empty()) { | 
| 363 |     return; | 
| 364 |   } | 
| 365 |   std::vector<Node*> nodes(parts.size()); | 
| 366 |   Node* node = &root_; | 
| 367 |   const Descriptor* current_descriptor = descriptor; | 
| 368 |   Node* new_branch_node = nullptr; | 
| 369 |   for (int i = 0; i < parts.size(); ++i) { | 
| 370 |     nodes[i] = node; | 
| 371 |     const FieldDescriptor* field_descriptor = | 
| 372 |         current_descriptor->FindFieldByName(name: parts[i]); | 
| 373 |     if (field_descriptor == nullptr || | 
| 374 |         (field_descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE && | 
| 375 |          i != parts.size() - 1)) { | 
| 376 |       // Invalid path. | 
| 377 |       if (new_branch_node != nullptr) { | 
| 378 |         // If add any new nodes, cleanup. | 
| 379 |         new_branch_node->ClearChildren(); | 
| 380 |       } | 
| 381 |       return; | 
| 382 |     } | 
| 383 |  | 
| 384 |     if (node->children.empty()) { | 
| 385 |       if (new_branch_node == nullptr) { | 
| 386 |         new_branch_node = node; | 
| 387 |       } | 
| 388 |       for (int j = 0; j < current_descriptor->field_count(); ++j) { | 
| 389 |         node->children[current_descriptor->field(index: j)->name()] = new Node(); | 
| 390 |       } | 
| 391 |     } | 
| 392 |     if (ContainsKey(collection: node->children, key: parts[i])) { | 
| 393 |       node = node->children[parts[i]]; | 
| 394 |       if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { | 
| 395 |         current_descriptor = field_descriptor->message_type(); | 
| 396 |       } | 
| 397 |     } else { | 
| 398 |       // Path does not exist. | 
| 399 |       return; | 
| 400 |     } | 
| 401 |   } | 
| 402 |   // Remove path. | 
| 403 |   for (int i = parts.size() - 1; i >= 0; i--) { | 
| 404 |     delete nodes[i]->children[parts[i]]; | 
| 405 |     nodes[i]->children.erase(x: parts[i]); | 
| 406 |     if (!nodes[i]->children.empty()) { | 
| 407 |       break; | 
| 408 |     } | 
| 409 |   } | 
| 410 | } | 
| 411 |  | 
| 412 | void FieldMaskTree::IntersectPath(const std::string& path, FieldMaskTree* out) { | 
| 413 |   std::vector<std::string> parts = Split(full: path, delim: "." ); | 
| 414 |   if (parts.empty()) { | 
| 415 |     return; | 
| 416 |   } | 
| 417 |   const Node* node = &root_; | 
| 418 |   for (const std::string& node_name : parts) { | 
| 419 |     if (node->children.empty()) { | 
| 420 |       if (node != &root_) { | 
| 421 |         out->AddPath(path); | 
| 422 |       } | 
| 423 |       return; | 
| 424 |     } | 
| 425 |     const Node* result = FindPtrOrNull(collection: node->children, key: node_name); | 
| 426 |     if (result == nullptr) { | 
| 427 |       // No intersection found. | 
| 428 |       return; | 
| 429 |     } | 
| 430 |     node = result; | 
| 431 |   } | 
| 432 |   // Now we found a matching node with the given path. Add all leaf nodes | 
| 433 |   // to out. | 
| 434 |   MergeLeafNodesToTree(prefix: path, node, out); | 
| 435 | } | 
| 436 |  | 
| 437 | void FieldMaskTree::MergeLeafNodesToTree(const std::string& prefix, | 
| 438 |                                          const Node* node, FieldMaskTree* out) { | 
| 439 |   if (node->children.empty()) { | 
| 440 |     out->AddPath(path: prefix); | 
| 441 |   } | 
| 442 |   for (std::map<std::string, Node*>::const_iterator it = node->children.begin(); | 
| 443 |        it != node->children.end(); ++it) { | 
| 444 |     std::string current_path = | 
| 445 |         prefix.empty() ? it->first : prefix + "."  + it->first; | 
| 446 |     MergeLeafNodesToTree(prefix: current_path, node: it->second, out); | 
| 447 |   } | 
| 448 | } | 
| 449 |  | 
| 450 | void FieldMaskTree::MergeMessage(const Node* node, const Message& source, | 
| 451 |                                  const FieldMaskUtil::MergeOptions& options, | 
| 452 |                                  Message* destination) { | 
| 453 |   GOOGLE_DCHECK(!node->children.empty()); | 
| 454 |   const Reflection* source_reflection = source.GetReflection(); | 
| 455 |   const Reflection* destination_reflection = destination->GetReflection(); | 
| 456 |   const Descriptor* descriptor = source.GetDescriptor(); | 
| 457 |   for (std::map<std::string, Node*>::const_iterator it = node->children.begin(); | 
| 458 |        it != node->children.end(); ++it) { | 
| 459 |     const std::string& field_name = it->first; | 
| 460 |     const Node* child = it->second; | 
| 461 |     const FieldDescriptor* field = descriptor->FindFieldByName(name: field_name); | 
| 462 |     if (field == nullptr) { | 
| 463 |       GOOGLE_LOG(ERROR) << "Cannot find field \""  << field_name << "\" in message "  | 
| 464 |                  << descriptor->full_name(); | 
| 465 |       continue; | 
| 466 |     } | 
| 467 |     if (!child->children.empty()) { | 
| 468 |       // Sub-paths are only allowed for singular message fields. | 
| 469 |       if (field->is_repeated() || | 
| 470 |           field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { | 
| 471 |         GOOGLE_LOG(ERROR) << "Field \""  << field_name << "\" in message "  | 
| 472 |                    << descriptor->full_name() | 
| 473 |                    << " is not a singular message field and cannot "  | 
| 474 |                    << "have sub-fields." ; | 
| 475 |         continue; | 
| 476 |       } | 
| 477 |       MergeMessage(node: child, source: source_reflection->GetMessage(message: source, field), options, | 
| 478 |                    destination: destination_reflection->MutableMessage(message: destination, field)); | 
| 479 |       continue; | 
| 480 |     } | 
| 481 |     if (!field->is_repeated()) { | 
| 482 |       switch (field->cpp_type()) { | 
| 483 | #define COPY_VALUE(TYPE, Name)                                              \ | 
| 484 |   case FieldDescriptor::CPPTYPE_##TYPE: {                                   \ | 
| 485 |     if (source_reflection->HasField(source, field)) {                       \ | 
| 486 |       destination_reflection->Set##Name(                                    \ | 
| 487 |           destination, field, source_reflection->Get##Name(source, field)); \ | 
| 488 |     } else {                                                                \ | 
| 489 |       destination_reflection->ClearField(destination, field);               \ | 
| 490 |     }                                                                       \ | 
| 491 |     break;                                                                  \ | 
| 492 |   } | 
| 493 |         COPY_VALUE(BOOL, Bool) | 
| 494 |         COPY_VALUE(INT32, Int32) | 
| 495 |         COPY_VALUE(INT64, Int64) | 
| 496 |         COPY_VALUE(UINT32, UInt32) | 
| 497 |         COPY_VALUE(UINT64, UInt64) | 
| 498 |         COPY_VALUE(FLOAT, Float) | 
| 499 |         COPY_VALUE(DOUBLE, Double) | 
| 500 |         COPY_VALUE(ENUM, Enum) | 
| 501 |         COPY_VALUE(STRING, String) | 
| 502 | #undef COPY_VALUE | 
| 503 |         case FieldDescriptor::CPPTYPE_MESSAGE: { | 
| 504 |           if (options.replace_message_fields()) { | 
| 505 |             destination_reflection->ClearField(message: destination, field); | 
| 506 |           } | 
| 507 |           if (source_reflection->HasField(message: source, field)) { | 
| 508 |             destination_reflection->MutableMessage(message: destination, field) | 
| 509 |                 ->MergeFrom(from: source_reflection->GetMessage(message: source, field)); | 
| 510 |           } | 
| 511 |           break; | 
| 512 |         } | 
| 513 |       } | 
| 514 |     } else { | 
| 515 |       if (options.replace_repeated_fields()) { | 
| 516 |         destination_reflection->ClearField(message: destination, field); | 
| 517 |       } | 
| 518 |       switch (field->cpp_type()) { | 
| 519 | #define COPY_REPEATED_VALUE(TYPE, Name)                            \ | 
| 520 |   case FieldDescriptor::CPPTYPE_##TYPE: {                          \ | 
| 521 |     int size = source_reflection->FieldSize(source, field);        \ | 
| 522 |     for (int i = 0; i < size; ++i) {                               \ | 
| 523 |       destination_reflection->Add##Name(                           \ | 
| 524 |           destination, field,                                      \ | 
| 525 |           source_reflection->GetRepeated##Name(source, field, i)); \ | 
| 526 |     }                                                              \ | 
| 527 |     break;                                                         \ | 
| 528 |   } | 
| 529 |         COPY_REPEATED_VALUE(BOOL, Bool) | 
| 530 |         COPY_REPEATED_VALUE(INT32, Int32) | 
| 531 |         COPY_REPEATED_VALUE(INT64, Int64) | 
| 532 |         COPY_REPEATED_VALUE(UINT32, UInt32) | 
| 533 |         COPY_REPEATED_VALUE(UINT64, UInt64) | 
| 534 |         COPY_REPEATED_VALUE(FLOAT, Float) | 
| 535 |         COPY_REPEATED_VALUE(DOUBLE, Double) | 
| 536 |         COPY_REPEATED_VALUE(ENUM, Enum) | 
| 537 |         COPY_REPEATED_VALUE(STRING, String) | 
| 538 | #undef COPY_REPEATED_VALUE | 
| 539 |         case FieldDescriptor::CPPTYPE_MESSAGE: { | 
| 540 |           int size = source_reflection->FieldSize(message: source, field); | 
| 541 |           for (int i = 0; i < size; ++i) { | 
| 542 |             destination_reflection->AddMessage(message: destination, field) | 
| 543 |                 ->MergeFrom( | 
| 544 |                     from: source_reflection->GetRepeatedMessage(message: source, field, index: i)); | 
| 545 |           } | 
| 546 |           break; | 
| 547 |         } | 
| 548 |       } | 
| 549 |     } | 
| 550 |   } | 
| 551 | } | 
| 552 |  | 
| 553 | void FieldMaskTree::AddRequiredFieldPath(Node* node, | 
| 554 |                                          const Descriptor* descriptor) { | 
| 555 |   const int32_t field_count = descriptor->field_count(); | 
| 556 |   for (int index = 0; index < field_count; ++index) { | 
| 557 |     const FieldDescriptor* field = descriptor->field(index); | 
| 558 |     if (field->is_required()) { | 
| 559 |       const std::string& node_name = field->name(); | 
| 560 |       Node*& child = node->children[node_name]; | 
| 561 |       if (child == nullptr) { | 
| 562 |         // Add required field path to the tree | 
| 563 |         child = new Node(); | 
| 564 |       } else if (child->children.empty()) { | 
| 565 |         // If the required field is in the tree and does not have any children, | 
| 566 |         // do nothing. | 
| 567 |         continue; | 
| 568 |       } | 
| 569 |       // Add required field in the children to the tree if the field is message. | 
| 570 |       if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { | 
| 571 |         AddRequiredFieldPath(node: child, descriptor: field->message_type()); | 
| 572 |       } | 
| 573 |     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { | 
| 574 |       std::map<std::string, Node*>::const_iterator it = | 
| 575 |           node->children.find(x: field->name()); | 
| 576 |       if (it != node->children.end()) { | 
| 577 |         // Add required fields in the children to the | 
| 578 |         // tree if the field is a message and present in the tree. | 
| 579 |         Node* child = it->second; | 
| 580 |         if (!child->children.empty()) { | 
| 581 |           AddRequiredFieldPath(node: child, descriptor: field->message_type()); | 
| 582 |         } | 
| 583 |       } | 
| 584 |     } | 
| 585 |   } | 
| 586 | } | 
| 587 |  | 
| 588 | bool FieldMaskTree::TrimMessage(const Node* node, Message* message) { | 
| 589 |   GOOGLE_DCHECK(!node->children.empty()); | 
| 590 |   const Reflection* reflection = message->GetReflection(); | 
| 591 |   const Descriptor* descriptor = message->GetDescriptor(); | 
| 592 |   const int32_t field_count = descriptor->field_count(); | 
| 593 |   bool modified = false; | 
| 594 |   for (int index = 0; index < field_count; ++index) { | 
| 595 |     const FieldDescriptor* field = descriptor->field(index); | 
| 596 |     std::map<std::string, Node*>::const_iterator it = | 
| 597 |         node->children.find(x: field->name()); | 
| 598 |     if (it == node->children.end()) { | 
| 599 |       if (field->is_repeated()) { | 
| 600 |         if (reflection->FieldSize(message: *message, field) != 0) { | 
| 601 |           modified = true; | 
| 602 |         } | 
| 603 |       } else { | 
| 604 |         if (reflection->HasField(message: *message, field)) { | 
| 605 |           modified = true; | 
| 606 |         } | 
| 607 |       } | 
| 608 |       reflection->ClearField(message, field); | 
| 609 |     } else { | 
| 610 |       if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { | 
| 611 |         Node* child = it->second; | 
| 612 |         if (!child->children.empty() && reflection->HasField(message: *message, field)) { | 
| 613 |           bool nestedMessageChanged = | 
| 614 |               TrimMessage(node: child, message: reflection->MutableMessage(message, field)); | 
| 615 |           modified = nestedMessageChanged || modified; | 
| 616 |         } | 
| 617 |       } | 
| 618 |     } | 
| 619 |   } | 
| 620 |   return modified; | 
| 621 | } | 
| 622 |  | 
| 623 | }  // namespace | 
| 624 |  | 
| 625 | void FieldMaskUtil::ToCanonicalForm(const FieldMask& mask, FieldMask* out) { | 
| 626 |   FieldMaskTree tree; | 
| 627 |   tree.MergeFromFieldMask(mask); | 
| 628 |   out->Clear(); | 
| 629 |   tree.MergeToFieldMask(mask: out); | 
| 630 | } | 
| 631 |  | 
| 632 | void FieldMaskUtil::Union(const FieldMask& mask1, const FieldMask& mask2, | 
| 633 |                           FieldMask* out) { | 
| 634 |   FieldMaskTree tree; | 
| 635 |   tree.MergeFromFieldMask(mask: mask1); | 
| 636 |   tree.MergeFromFieldMask(mask: mask2); | 
| 637 |   out->Clear(); | 
| 638 |   tree.MergeToFieldMask(mask: out); | 
| 639 | } | 
| 640 |  | 
| 641 | void FieldMaskUtil::Intersect(const FieldMask& mask1, const FieldMask& mask2, | 
| 642 |                               FieldMask* out) { | 
| 643 |   FieldMaskTree tree, intersection; | 
| 644 |   tree.MergeFromFieldMask(mask: mask1); | 
| 645 |   for (int i = 0; i < mask2.paths_size(); ++i) { | 
| 646 |     tree.IntersectPath(path: mask2.paths(index: i), out: &intersection); | 
| 647 |   } | 
| 648 |   out->Clear(); | 
| 649 |   intersection.MergeToFieldMask(mask: out); | 
| 650 | } | 
| 651 |  | 
| 652 | void FieldMaskUtil::Subtract(const Descriptor* descriptor, | 
| 653 |                              const FieldMask& mask1, const FieldMask& mask2, | 
| 654 |                              FieldMask* out) { | 
| 655 |   if (mask1.paths().empty()) { | 
| 656 |     out->Clear(); | 
| 657 |     return; | 
| 658 |   } | 
| 659 |   FieldMaskTree tree; | 
| 660 |   tree.MergeFromFieldMask(mask: mask1); | 
| 661 |   for (int i = 0; i < mask2.paths_size(); ++i) { | 
| 662 |     tree.RemovePath(path: mask2.paths(index: i), descriptor); | 
| 663 |   } | 
| 664 |   out->Clear(); | 
| 665 |   tree.MergeToFieldMask(mask: out); | 
| 666 | } | 
| 667 |  | 
| 668 | bool FieldMaskUtil::IsPathInFieldMask(StringPiece path, | 
| 669 |                                       const FieldMask& mask) { | 
| 670 |   for (int i = 0; i < mask.paths_size(); ++i) { | 
| 671 |     const std::string& mask_path = mask.paths(index: i); | 
| 672 |     if (path == mask_path) { | 
| 673 |       return true; | 
| 674 |     } else if (mask_path.length() < path.length()) { | 
| 675 |       // Also check whether mask.paths(i) is a prefix of path. | 
| 676 |       if (path.substr(pos: 0, n: mask_path.length() + 1).compare(x: mask_path + "." ) == | 
| 677 |           0) { | 
| 678 |         return true; | 
| 679 |       } | 
| 680 |     } | 
| 681 |   } | 
| 682 |   return false; | 
| 683 | } | 
| 684 |  | 
| 685 | void FieldMaskUtil::MergeMessageTo(const Message& source, const FieldMask& mask, | 
| 686 |                                    const MergeOptions& options, | 
| 687 |                                    Message* destination) { | 
| 688 |   GOOGLE_CHECK(source.GetDescriptor() == destination->GetDescriptor()); | 
| 689 |   // Build a FieldMaskTree and walk through the tree to merge all specified | 
| 690 |   // fields. | 
| 691 |   FieldMaskTree tree; | 
| 692 |   tree.MergeFromFieldMask(mask); | 
| 693 |   tree.MergeMessage(source, options, destination); | 
| 694 | } | 
| 695 |  | 
| 696 | bool FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* message) { | 
| 697 |   // Build a FieldMaskTree and walk through the tree to merge all specified | 
| 698 |   // fields. | 
| 699 |   FieldMaskTree tree; | 
| 700 |   tree.MergeFromFieldMask(mask); | 
| 701 |   return tree.TrimMessage(GOOGLE_CHECK_NOTNULL(message)); | 
| 702 | } | 
| 703 |  | 
| 704 | bool FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* message, | 
| 705 |                                 const TrimOptions& options) { | 
| 706 |   // Build a FieldMaskTree and walk through the tree to merge all specified | 
| 707 |   // fields. | 
| 708 |   FieldMaskTree tree; | 
| 709 |   tree.MergeFromFieldMask(mask); | 
| 710 |   // If keep_required_fields is true, implicitly add required fields of | 
| 711 |   // a message present in the tree to prevent from trimming. | 
| 712 |   if (options.keep_required_fields()) { | 
| 713 |     tree.AddRequiredFieldPath(GOOGLE_CHECK_NOTNULL(message->GetDescriptor())); | 
| 714 |   } | 
| 715 |   return tree.TrimMessage(GOOGLE_CHECK_NOTNULL(message)); | 
| 716 | } | 
| 717 |  | 
| 718 | }  // namespace util | 
| 719 | }  // namespace protobuf | 
| 720 | }  // namespace google | 
| 721 |  |