| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 namespace util { | 38 namespace util { |
| 39 | 39 |
| 40 using google::protobuf::FieldMask; | 40 using google::protobuf::FieldMask; |
| 41 | 41 |
| 42 string FieldMaskUtil::ToString(const FieldMask& mask) { | 42 string FieldMaskUtil::ToString(const FieldMask& mask) { |
| 43 return Join(mask.paths(), ","); | 43 return Join(mask.paths(), ","); |
| 44 } | 44 } |
| 45 | 45 |
| 46 void FieldMaskUtil::FromString(StringPiece str, FieldMask* out) { | 46 void FieldMaskUtil::FromString(StringPiece str, FieldMask* out) { |
| 47 out->Clear(); | 47 out->Clear(); |
| 48 vector<string> paths = Split(str, ","); | 48 std::vector<string> paths = Split(str, ","); |
| 49 for (int i = 0; i < paths.size(); ++i) { | 49 for (int i = 0; i < paths.size(); ++i) { |
| 50 if (paths[i].empty()) continue; | 50 if (paths[i].empty()) continue; |
| 51 out->add_paths(paths[i]); | 51 out->add_paths(paths[i]); |
| 52 } | 52 } |
| 53 } | 53 } |
| 54 | 54 |
| 55 bool FieldMaskUtil::SnakeCaseToCamelCase(StringPiece input, string* output) { | 55 bool FieldMaskUtil::SnakeCaseToCamelCase(StringPiece input, string* output) { |
| 56 output->clear(); | 56 output->clear(); |
| 57 bool after_underscore = false; | 57 bool after_underscore = false; |
| 58 for (int i = 0; i < input.size(); ++i) { | 58 for (int i = 0; i < input.size(); ++i) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 if (i > 0) { | 109 if (i > 0) { |
| 110 out->push_back(','); | 110 out->push_back(','); |
| 111 } | 111 } |
| 112 out->append(camelcase_path); | 112 out->append(camelcase_path); |
| 113 } | 113 } |
| 114 return true; | 114 return true; |
| 115 } | 115 } |
| 116 | 116 |
| 117 bool FieldMaskUtil::FromJsonString(StringPiece str, FieldMask* out) { | 117 bool FieldMaskUtil::FromJsonString(StringPiece str, FieldMask* out) { |
| 118 out->Clear(); | 118 out->Clear(); |
| 119 vector<string> paths = Split(str, ","); | 119 std::vector<string> paths = Split(str, ","); |
| 120 for (int i = 0; i < paths.size(); ++i) { | 120 for (int i = 0; i < paths.size(); ++i) { |
| 121 if (paths[i].empty()) continue; | 121 if (paths[i].empty()) continue; |
| 122 string snakecase_path; | 122 string snakecase_path; |
| 123 if (!CamelCaseToSnakeCase(paths[i], &snakecase_path)) { | 123 if (!CamelCaseToSnakeCase(paths[i], &snakecase_path)) { |
| 124 return false; | 124 return false; |
| 125 } | 125 } |
| 126 out->add_paths(snakecase_path); | 126 out->add_paths(snakecase_path); |
| 127 } | 127 } |
| 128 return true; | 128 return true; |
| 129 } | 129 } |
| 130 | 130 |
| 131 bool FieldMaskUtil::InternalIsValidPath(const Descriptor* descriptor, | 131 bool FieldMaskUtil::GetFieldDescriptors( |
| 132 StringPiece path) { | 132 const Descriptor* descriptor, StringPiece path, |
| 133 vector<string> parts = Split(path, "."); | 133 std::vector<const FieldDescriptor*>* field_descriptors) { |
| 134 if (field_descriptors != NULL) { |
| 135 field_descriptors->clear(); |
| 136 } |
| 137 std::vector<string> parts = Split(path, "."); |
| 134 for (int i = 0; i < parts.size(); ++i) { | 138 for (int i = 0; i < parts.size(); ++i) { |
| 135 const string& field_name = parts[i]; | 139 const string& field_name = parts[i]; |
| 136 if (descriptor == NULL) { | 140 if (descriptor == NULL) { |
| 137 return false; | 141 return false; |
| 138 } | 142 } |
| 139 const FieldDescriptor* field = descriptor->FindFieldByName(field_name); | 143 const FieldDescriptor* field = descriptor->FindFieldByName(field_name); |
| 140 if (field == NULL) { | 144 if (field == NULL) { |
| 141 return false; | 145 return false; |
| 142 } | 146 } |
| 147 if (field_descriptors != NULL) { |
| 148 field_descriptors->push_back(field); |
| 149 } |
| 143 if (!field->is_repeated() && | 150 if (!field->is_repeated() && |
| 144 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { | 151 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
| 145 descriptor = field->message_type(); | 152 descriptor = field->message_type(); |
| 146 } else { | 153 } else { |
| 147 descriptor = NULL; | 154 descriptor = NULL; |
| 148 } | 155 } |
| 149 } | 156 } |
| 150 return true; | 157 return true; |
| 151 } | 158 } |
| 152 | 159 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 void MergeMessage(const Message& source, | 200 void MergeMessage(const Message& source, |
| 194 const FieldMaskUtil::MergeOptions& options, | 201 const FieldMaskUtil::MergeOptions& options, |
| 195 Message* destination) { | 202 Message* destination) { |
| 196 // Do nothing if the tree is empty. | 203 // Do nothing if the tree is empty. |
| 197 if (root_.children.empty()) { | 204 if (root_.children.empty()) { |
| 198 return; | 205 return; |
| 199 } | 206 } |
| 200 MergeMessage(&root_, source, options, destination); | 207 MergeMessage(&root_, source, options, destination); |
| 201 } | 208 } |
| 202 | 209 |
| 210 // Trims all fields not specified by this tree from the given message. |
| 211 void TrimMessage(Message* message) { |
| 212 // Do nothing if the tree is empty. |
| 213 if (root_.children.empty()) { |
| 214 return; |
| 215 } |
| 216 TrimMessage(&root_, message); |
| 217 } |
| 218 |
| 203 private: | 219 private: |
| 204 struct Node { | 220 struct Node { |
| 205 Node() {} | 221 Node() {} |
| 206 | 222 |
| 207 ~Node() { ClearChildren(); } | 223 ~Node() { ClearChildren(); } |
| 208 | 224 |
| 209 void ClearChildren() { | 225 void ClearChildren() { |
| 210 for (map<string, Node*>::iterator it = children.begin(); | 226 for (std::map<string, Node*>::iterator it = children.begin(); |
| 211 it != children.end(); ++it) { | 227 it != children.end(); ++it) { |
| 212 delete it->second; | 228 delete it->second; |
| 213 } | 229 } |
| 214 children.clear(); | 230 children.clear(); |
| 215 } | 231 } |
| 216 | 232 |
| 217 map<string, Node*> children; | 233 std::map<string, Node*> children; |
| 218 | 234 |
| 219 private: | 235 private: |
| 220 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node); | 236 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node); |
| 221 }; | 237 }; |
| 222 | 238 |
| 223 // Merge a sub-tree to mask. This method adds the field paths represented | 239 // Merge a sub-tree to mask. This method adds the field paths represented |
| 224 // by all leaf nodes descended from "node" to mask. | 240 // by all leaf nodes descended from "node" to mask. |
| 225 void MergeToFieldMask(const string& prefix, const Node* node, FieldMask* out); | 241 void MergeToFieldMask(const string& prefix, const Node* node, FieldMask* out); |
| 226 | 242 |
| 227 // Merge all leaf nodes of a sub-tree to another tree. | 243 // Merge all leaf nodes of a sub-tree to another tree. |
| 228 void MergeLeafNodesToTree(const string& prefix, const Node* node, | 244 void MergeLeafNodesToTree(const string& prefix, const Node* node, |
| 229 FieldMaskTree* out); | 245 FieldMaskTree* out); |
| 230 | 246 |
| 231 // Merge all fields specified by a sub-tree from one message to another. | 247 // Merge all fields specified by a sub-tree from one message to another. |
| 232 void MergeMessage(const Node* node, const Message& source, | 248 void MergeMessage(const Node* node, const Message& source, |
| 233 const FieldMaskUtil::MergeOptions& options, | 249 const FieldMaskUtil::MergeOptions& options, |
| 234 Message* destination); | 250 Message* destination); |
| 235 | 251 |
| 252 // Trims all fields not specified by this sub-tree from the given message. |
| 253 void TrimMessage(const Node* node, Message* message); |
| 254 |
| 236 Node root_; | 255 Node root_; |
| 237 | 256 |
| 238 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldMaskTree); | 257 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldMaskTree); |
| 239 }; | 258 }; |
| 240 | 259 |
| 241 FieldMaskTree::FieldMaskTree() {} | 260 FieldMaskTree::FieldMaskTree() {} |
| 242 | 261 |
| 243 FieldMaskTree::~FieldMaskTree() {} | 262 FieldMaskTree::~FieldMaskTree() {} |
| 244 | 263 |
| 245 void FieldMaskTree::MergeFromFieldMask(const FieldMask& mask) { | 264 void FieldMaskTree::MergeFromFieldMask(const FieldMask& mask) { |
| 246 for (int i = 0; i < mask.paths_size(); ++i) { | 265 for (int i = 0; i < mask.paths_size(); ++i) { |
| 247 AddPath(mask.paths(i)); | 266 AddPath(mask.paths(i)); |
| 248 } | 267 } |
| 249 } | 268 } |
| 250 | 269 |
| 251 void FieldMaskTree::MergeToFieldMask(FieldMask* mask) { | 270 void FieldMaskTree::MergeToFieldMask(FieldMask* mask) { |
| 252 MergeToFieldMask("", &root_, mask); | 271 MergeToFieldMask("", &root_, mask); |
| 253 } | 272 } |
| 254 | 273 |
| 255 void FieldMaskTree::MergeToFieldMask(const string& prefix, const Node* node, | 274 void FieldMaskTree::MergeToFieldMask(const string& prefix, const Node* node, |
| 256 FieldMask* out) { | 275 FieldMask* out) { |
| 257 if (node->children.empty()) { | 276 if (node->children.empty()) { |
| 258 if (prefix.empty()) { | 277 if (prefix.empty()) { |
| 259 // This is the root node. | 278 // This is the root node. |
| 260 return; | 279 return; |
| 261 } | 280 } |
| 262 out->add_paths(prefix); | 281 out->add_paths(prefix); |
| 263 return; | 282 return; |
| 264 } | 283 } |
| 265 for (map<string, Node*>::const_iterator it = node->children.begin(); | 284 for (std::map<string, Node*>::const_iterator it = node->children.begin(); |
| 266 it != node->children.end(); ++it) { | 285 it != node->children.end(); ++it) { |
| 267 string current_path = prefix.empty() ? it->first : prefix + "." + it->first; | 286 string current_path = prefix.empty() ? it->first : prefix + "." + it->first; |
| 268 MergeToFieldMask(current_path, it->second, out); | 287 MergeToFieldMask(current_path, it->second, out); |
| 269 } | 288 } |
| 270 } | 289 } |
| 271 | 290 |
| 272 void FieldMaskTree::AddPath(const string& path) { | 291 void FieldMaskTree::AddPath(const string& path) { |
| 273 vector<string> parts = Split(path, "."); | 292 std::vector<string> parts = Split(path, "."); |
| 274 if (parts.empty()) { | 293 if (parts.empty()) { |
| 275 return; | 294 return; |
| 276 } | 295 } |
| 277 bool new_branch = false; | 296 bool new_branch = false; |
| 278 Node* node = &root_; | 297 Node* node = &root_; |
| 279 for (int i = 0; i < parts.size(); ++i) { | 298 for (int i = 0; i < parts.size(); ++i) { |
| 280 if (!new_branch && node != &root_ && node->children.empty()) { | 299 if (!new_branch && node != &root_ && node->children.empty()) { |
| 281 // Path matches an existing leaf node. This means the path is already | 300 // Path matches an existing leaf node. This means the path is already |
| 282 // coverred by this tree (for example, adding "foo.bar.baz" to a tree | 301 // coverred by this tree (for example, adding "foo.bar.baz" to a tree |
| 283 // which already contains "foo.bar"). | 302 // which already contains "foo.bar"). |
| 284 return; | 303 return; |
| 285 } | 304 } |
| 286 const string& node_name = parts[i]; | 305 const string& node_name = parts[i]; |
| 287 Node*& child = node->children[node_name]; | 306 Node*& child = node->children[node_name]; |
| 288 if (child == NULL) { | 307 if (child == NULL) { |
| 289 new_branch = true; | 308 new_branch = true; |
| 290 child = new Node(); | 309 child = new Node(); |
| 291 } | 310 } |
| 292 node = child; | 311 node = child; |
| 293 } | 312 } |
| 294 if (!node->children.empty()) { | 313 if (!node->children.empty()) { |
| 295 node->ClearChildren(); | 314 node->ClearChildren(); |
| 296 } | 315 } |
| 297 } | 316 } |
| 298 | 317 |
| 299 void FieldMaskTree::IntersectPath(const string& path, FieldMaskTree* out) { | 318 void FieldMaskTree::IntersectPath(const string& path, FieldMaskTree* out) { |
| 300 vector<string> parts = Split(path, "."); | 319 std::vector<string> parts = Split(path, "."); |
| 301 if (parts.empty()) { | 320 if (parts.empty()) { |
| 302 return; | 321 return; |
| 303 } | 322 } |
| 304 const Node* node = &root_; | 323 const Node* node = &root_; |
| 305 for (int i = 0; i < parts.size(); ++i) { | 324 for (int i = 0; i < parts.size(); ++i) { |
| 306 if (node->children.empty()) { | 325 if (node->children.empty()) { |
| 307 if (node != &root_) { | 326 if (node != &root_) { |
| 308 out->AddPath(path); | 327 out->AddPath(path); |
| 309 } | 328 } |
| 310 return; | 329 return; |
| 311 } | 330 } |
| 312 const string& node_name = parts[i]; | 331 const string& node_name = parts[i]; |
| 313 const Node* result = FindPtrOrNull(node->children, node_name); | 332 const Node* result = FindPtrOrNull(node->children, node_name); |
| 314 if (result == NULL) { | 333 if (result == NULL) { |
| 315 // No intersection found. | 334 // No intersection found. |
| 316 return; | 335 return; |
| 317 } | 336 } |
| 318 node = result; | 337 node = result; |
| 319 } | 338 } |
| 320 // Now we found a matching node with the given path. Add all leaf nodes | 339 // Now we found a matching node with the given path. Add all leaf nodes |
| 321 // to out. | 340 // to out. |
| 322 MergeLeafNodesToTree(path, node, out); | 341 MergeLeafNodesToTree(path, node, out); |
| 323 } | 342 } |
| 324 | 343 |
| 325 void FieldMaskTree::MergeLeafNodesToTree(const string& prefix, const Node* node, | 344 void FieldMaskTree::MergeLeafNodesToTree(const string& prefix, const Node* node, |
| 326 FieldMaskTree* out) { | 345 FieldMaskTree* out) { |
| 327 if (node->children.empty()) { | 346 if (node->children.empty()) { |
| 328 out->AddPath(prefix); | 347 out->AddPath(prefix); |
| 329 } | 348 } |
| 330 for (map<string, Node*>::const_iterator it = node->children.begin(); | 349 for (std::map<string, Node*>::const_iterator it = node->children.begin(); |
| 331 it != node->children.end(); ++it) { | 350 it != node->children.end(); ++it) { |
| 332 string current_path = prefix.empty() ? it->first : prefix + "." + it->first; | 351 string current_path = prefix.empty() ? it->first : prefix + "." + it->first; |
| 333 MergeLeafNodesToTree(current_path, it->second, out); | 352 MergeLeafNodesToTree(current_path, it->second, out); |
| 334 } | 353 } |
| 335 } | 354 } |
| 336 | 355 |
| 337 void FieldMaskTree::MergeMessage(const Node* node, const Message& source, | 356 void FieldMaskTree::MergeMessage(const Node* node, const Message& source, |
| 338 const FieldMaskUtil::MergeOptions& options, | 357 const FieldMaskUtil::MergeOptions& options, |
| 339 Message* destination) { | 358 Message* destination) { |
| 340 GOOGLE_DCHECK(!node->children.empty()); | 359 GOOGLE_DCHECK(!node->children.empty()); |
| 341 const Reflection* source_reflection = source.GetReflection(); | 360 const Reflection* source_reflection = source.GetReflection(); |
| 342 const Reflection* destination_reflection = destination->GetReflection(); | 361 const Reflection* destination_reflection = destination->GetReflection(); |
| 343 const Descriptor* descriptor = source.GetDescriptor(); | 362 const Descriptor* descriptor = source.GetDescriptor(); |
| 344 for (map<string, Node*>::const_iterator it = node->children.begin(); | 363 for (std::map<string, Node*>::const_iterator it = node->children.begin(); |
| 345 it != node->children.end(); ++it) { | 364 it != node->children.end(); ++it) { |
| 346 const string& field_name = it->first; | 365 const string& field_name = it->first; |
| 347 const Node* child = it->second; | 366 const Node* child = it->second; |
| 348 const FieldDescriptor* field = descriptor->FindFieldByName(field_name); | 367 const FieldDescriptor* field = descriptor->FindFieldByName(field_name); |
| 349 if (field == NULL) { | 368 if (field == NULL) { |
| 350 GOOGLE_LOG(ERROR) << "Cannot find field \"" << field_name << "\" in messag
e " | 369 GOOGLE_LOG(ERROR) << "Cannot find field \"" << field_name << "\" in messag
e " |
| 351 << descriptor->full_name(); | 370 << descriptor->full_name(); |
| 352 continue; | 371 continue; |
| 353 } | 372 } |
| 354 if (!child->children.empty()) { | 373 if (!child->children.empty()) { |
| 355 // Sub-paths are only allowed for singular message fields. | 374 // Sub-paths are only allowed for singular message fields. |
| 356 if (field->is_repeated() || | 375 if (field->is_repeated() || |
| 357 field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { | 376 field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { |
| 358 GOOGLE_LOG(ERROR) << "Field \"" << field_name << "\" in message " | 377 GOOGLE_LOG(ERROR) << "Field \"" << field_name << "\" in message " |
| 359 << descriptor->full_name() | 378 << descriptor->full_name() |
| 360 << " is not a singular message field and cannot " | 379 << " is not a singular message field and cannot " |
| 361 << "have sub-fields."; | 380 << "have sub-fields."; |
| 362 continue; | 381 continue; |
| 363 } | 382 } |
| 364 MergeMessage(child, source_reflection->GetMessage(source, field), options, | 383 MergeMessage(child, source_reflection->GetMessage(source, field), options, |
| 365 destination_reflection->MutableMessage(destination, field)); | 384 destination_reflection->MutableMessage(destination, field)); |
| 366 continue; | 385 continue; |
| 367 } | 386 } |
| 368 if (!field->is_repeated()) { | 387 if (!field->is_repeated()) { |
| 369 switch (field->cpp_type()) { | 388 switch (field->cpp_type()) { |
| 370 #define COPY_VALUE(TYPE, Name) \ | 389 #define COPY_VALUE(TYPE, Name) \ |
| 371 case FieldDescriptor::CPPTYPE_##TYPE: { \ | 390 case FieldDescriptor::CPPTYPE_##TYPE: { \ |
| 372 destination_reflection->Set##Name( \ | 391 if (source_reflection->HasField(source, field)) { \ |
| 373 destination, field, source_reflection->Get##Name(source, field)); \ | 392 destination_reflection->Set##Name( \ |
| 374 break; \ | 393 destination, field, source_reflection->Get##Name(source, field)); \ |
| 394 } else { \ |
| 395 destination_reflection->ClearField(destination, field); \ |
| 396 } \ |
| 397 break; \ |
| 375 } | 398 } |
| 376 COPY_VALUE(BOOL, Bool) | 399 COPY_VALUE(BOOL, Bool) |
| 377 COPY_VALUE(INT32, Int32) | 400 COPY_VALUE(INT32, Int32) |
| 378 COPY_VALUE(INT64, Int64) | 401 COPY_VALUE(INT64, Int64) |
| 379 COPY_VALUE(UINT32, UInt32) | 402 COPY_VALUE(UINT32, UInt32) |
| 380 COPY_VALUE(UINT64, UInt64) | 403 COPY_VALUE(UINT64, UInt64) |
| 381 COPY_VALUE(FLOAT, Float) | 404 COPY_VALUE(FLOAT, Float) |
| 382 COPY_VALUE(DOUBLE, Double) | 405 COPY_VALUE(DOUBLE, Double) |
| 383 COPY_VALUE(ENUM, Enum) | 406 COPY_VALUE(ENUM, Enum) |
| 384 COPY_VALUE(STRING, String) | 407 COPY_VALUE(STRING, String) |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 ->MergeFrom( | 449 ->MergeFrom( |
| 427 source_reflection->GetRepeatedMessage(source, field, i)); | 450 source_reflection->GetRepeatedMessage(source, field, i)); |
| 428 } | 451 } |
| 429 break; | 452 break; |
| 430 } | 453 } |
| 431 } | 454 } |
| 432 } | 455 } |
| 433 } | 456 } |
| 434 } | 457 } |
| 435 | 458 |
| 459 void FieldMaskTree::TrimMessage(const Node* node, Message* message) { |
| 460 GOOGLE_DCHECK(!node->children.empty()); |
| 461 const Reflection* reflection = message->GetReflection(); |
| 462 const Descriptor* descriptor = message->GetDescriptor(); |
| 463 const int32 field_count = descriptor->field_count(); |
| 464 for (int index = 0; index < field_count; ++index) { |
| 465 const FieldDescriptor* field = descriptor->field(index); |
| 466 map<string, Node*>::const_iterator it = node->children.find(field->name()); |
| 467 if (it == node->children.end()) { |
| 468 reflection->ClearField(message, field); |
| 469 } else { |
| 470 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
| 471 Node* child = it->second; |
| 472 if (!child->children.empty()) { |
| 473 TrimMessage(child, reflection->MutableMessage(message, field)); |
| 474 } |
| 475 } |
| 476 } |
| 477 } |
| 478 } |
| 479 |
| 436 } // namespace | 480 } // namespace |
| 437 | 481 |
| 438 void FieldMaskUtil::ToCanonicalForm(const FieldMask& mask, FieldMask* out) { | 482 void FieldMaskUtil::ToCanonicalForm(const FieldMask& mask, FieldMask* out) { |
| 439 FieldMaskTree tree; | 483 FieldMaskTree tree; |
| 440 tree.MergeFromFieldMask(mask); | 484 tree.MergeFromFieldMask(mask); |
| 441 out->Clear(); | 485 out->Clear(); |
| 442 tree.MergeToFieldMask(out); | 486 tree.MergeToFieldMask(out); |
| 443 } | 487 } |
| 444 | 488 |
| 445 void FieldMaskUtil::Union(const FieldMask& mask1, const FieldMask& mask2, | 489 void FieldMaskUtil::Union(const FieldMask& mask1, const FieldMask& mask2, |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 482 const MergeOptions& options, | 526 const MergeOptions& options, |
| 483 Message* destination) { | 527 Message* destination) { |
| 484 GOOGLE_CHECK(source.GetDescriptor() == destination->GetDescriptor()); | 528 GOOGLE_CHECK(source.GetDescriptor() == destination->GetDescriptor()); |
| 485 // Build a FieldMaskTree and walk through the tree to merge all specified | 529 // Build a FieldMaskTree and walk through the tree to merge all specified |
| 486 // fields. | 530 // fields. |
| 487 FieldMaskTree tree; | 531 FieldMaskTree tree; |
| 488 tree.MergeFromFieldMask(mask); | 532 tree.MergeFromFieldMask(mask); |
| 489 tree.MergeMessage(source, options, destination); | 533 tree.MergeMessage(source, options, destination); |
| 490 } | 534 } |
| 491 | 535 |
| 536 void FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* destination) { |
| 537 // Build a FieldMaskTree and walk through the tree to merge all specified |
| 538 // fields. |
| 539 FieldMaskTree tree; |
| 540 tree.MergeFromFieldMask(mask); |
| 541 tree.TrimMessage(GOOGLE_CHECK_NOTNULL(destination)); |
| 542 } |
| 543 |
| 492 } // namespace util | 544 } // namespace util |
| 493 } // namespace protobuf | 545 } // namespace protobuf |
| 494 } // namespace google | 546 } // namespace google |
| OLD | NEW |