| 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 std::vector<string> paths = Split(str, ","); | 48 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 std::vector<string> paths = Split(str, ","); | 119 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::GetFieldDescriptors( | 131 bool FieldMaskUtil::InternalIsValidPath(const Descriptor* descriptor, |
| 132 const Descriptor* descriptor, StringPiece path, | 132 StringPiece path) { |
| 133 std::vector<const FieldDescriptor*>* field_descriptors) { | 133 vector<string> parts = Split(path, "."); |
| 134 if (field_descriptors != NULL) { | |
| 135 field_descriptors->clear(); | |
| 136 } | |
| 137 std::vector<string> parts = Split(path, "."); | |
| 138 for (int i = 0; i < parts.size(); ++i) { | 134 for (int i = 0; i < parts.size(); ++i) { |
| 139 const string& field_name = parts[i]; | 135 const string& field_name = parts[i]; |
| 140 if (descriptor == NULL) { | 136 if (descriptor == NULL) { |
| 141 return false; | 137 return false; |
| 142 } | 138 } |
| 143 const FieldDescriptor* field = descriptor->FindFieldByName(field_name); | 139 const FieldDescriptor* field = descriptor->FindFieldByName(field_name); |
| 144 if (field == NULL) { | 140 if (field == NULL) { |
| 145 return false; | 141 return false; |
| 146 } | 142 } |
| 147 if (field_descriptors != NULL) { | |
| 148 field_descriptors->push_back(field); | |
| 149 } | |
| 150 if (!field->is_repeated() && | 143 if (!field->is_repeated() && |
| 151 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { | 144 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
| 152 descriptor = field->message_type(); | 145 descriptor = field->message_type(); |
| 153 } else { | 146 } else { |
| 154 descriptor = NULL; | 147 descriptor = NULL; |
| 155 } | 148 } |
| 156 } | 149 } |
| 157 return true; | 150 return true; |
| 158 } | 151 } |
| 159 | 152 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 void MergeMessage(const Message& source, | 193 void MergeMessage(const Message& source, |
| 201 const FieldMaskUtil::MergeOptions& options, | 194 const FieldMaskUtil::MergeOptions& options, |
| 202 Message* destination) { | 195 Message* destination) { |
| 203 // Do nothing if the tree is empty. | 196 // Do nothing if the tree is empty. |
| 204 if (root_.children.empty()) { | 197 if (root_.children.empty()) { |
| 205 return; | 198 return; |
| 206 } | 199 } |
| 207 MergeMessage(&root_, source, options, destination); | 200 MergeMessage(&root_, source, options, destination); |
| 208 } | 201 } |
| 209 | 202 |
| 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 | |
| 219 private: | 203 private: |
| 220 struct Node { | 204 struct Node { |
| 221 Node() {} | 205 Node() {} |
| 222 | 206 |
| 223 ~Node() { ClearChildren(); } | 207 ~Node() { ClearChildren(); } |
| 224 | 208 |
| 225 void ClearChildren() { | 209 void ClearChildren() { |
| 226 for (std::map<string, Node*>::iterator it = children.begin(); | 210 for (map<string, Node*>::iterator it = children.begin(); |
| 227 it != children.end(); ++it) { | 211 it != children.end(); ++it) { |
| 228 delete it->second; | 212 delete it->second; |
| 229 } | 213 } |
| 230 children.clear(); | 214 children.clear(); |
| 231 } | 215 } |
| 232 | 216 |
| 233 std::map<string, Node*> children; | 217 map<string, Node*> children; |
| 234 | 218 |
| 235 private: | 219 private: |
| 236 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node); | 220 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node); |
| 237 }; | 221 }; |
| 238 | 222 |
| 239 // Merge a sub-tree to mask. This method adds the field paths represented | 223 // Merge a sub-tree to mask. This method adds the field paths represented |
| 240 // by all leaf nodes descended from "node" to mask. | 224 // by all leaf nodes descended from "node" to mask. |
| 241 void MergeToFieldMask(const string& prefix, const Node* node, FieldMask* out); | 225 void MergeToFieldMask(const string& prefix, const Node* node, FieldMask* out); |
| 242 | 226 |
| 243 // Merge all leaf nodes of a sub-tree to another tree. | 227 // Merge all leaf nodes of a sub-tree to another tree. |
| 244 void MergeLeafNodesToTree(const string& prefix, const Node* node, | 228 void MergeLeafNodesToTree(const string& prefix, const Node* node, |
| 245 FieldMaskTree* out); | 229 FieldMaskTree* out); |
| 246 | 230 |
| 247 // Merge all fields specified by a sub-tree from one message to another. | 231 // Merge all fields specified by a sub-tree from one message to another. |
| 248 void MergeMessage(const Node* node, const Message& source, | 232 void MergeMessage(const Node* node, const Message& source, |
| 249 const FieldMaskUtil::MergeOptions& options, | 233 const FieldMaskUtil::MergeOptions& options, |
| 250 Message* destination); | 234 Message* destination); |
| 251 | 235 |
| 252 // Trims all fields not specified by this sub-tree from the given message. | |
| 253 void TrimMessage(const Node* node, Message* message); | |
| 254 | |
| 255 Node root_; | 236 Node root_; |
| 256 | 237 |
| 257 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldMaskTree); | 238 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldMaskTree); |
| 258 }; | 239 }; |
| 259 | 240 |
| 260 FieldMaskTree::FieldMaskTree() {} | 241 FieldMaskTree::FieldMaskTree() {} |
| 261 | 242 |
| 262 FieldMaskTree::~FieldMaskTree() {} | 243 FieldMaskTree::~FieldMaskTree() {} |
| 263 | 244 |
| 264 void FieldMaskTree::MergeFromFieldMask(const FieldMask& mask) { | 245 void FieldMaskTree::MergeFromFieldMask(const FieldMask& mask) { |
| 265 for (int i = 0; i < mask.paths_size(); ++i) { | 246 for (int i = 0; i < mask.paths_size(); ++i) { |
| 266 AddPath(mask.paths(i)); | 247 AddPath(mask.paths(i)); |
| 267 } | 248 } |
| 268 } | 249 } |
| 269 | 250 |
| 270 void FieldMaskTree::MergeToFieldMask(FieldMask* mask) { | 251 void FieldMaskTree::MergeToFieldMask(FieldMask* mask) { |
| 271 MergeToFieldMask("", &root_, mask); | 252 MergeToFieldMask("", &root_, mask); |
| 272 } | 253 } |
| 273 | 254 |
| 274 void FieldMaskTree::MergeToFieldMask(const string& prefix, const Node* node, | 255 void FieldMaskTree::MergeToFieldMask(const string& prefix, const Node* node, |
| 275 FieldMask* out) { | 256 FieldMask* out) { |
| 276 if (node->children.empty()) { | 257 if (node->children.empty()) { |
| 277 if (prefix.empty()) { | 258 if (prefix.empty()) { |
| 278 // This is the root node. | 259 // This is the root node. |
| 279 return; | 260 return; |
| 280 } | 261 } |
| 281 out->add_paths(prefix); | 262 out->add_paths(prefix); |
| 282 return; | 263 return; |
| 283 } | 264 } |
| 284 for (std::map<string, Node*>::const_iterator it = node->children.begin(); | 265 for (map<string, Node*>::const_iterator it = node->children.begin(); |
| 285 it != node->children.end(); ++it) { | 266 it != node->children.end(); ++it) { |
| 286 string current_path = prefix.empty() ? it->first : prefix + "." + it->first; | 267 string current_path = prefix.empty() ? it->first : prefix + "." + it->first; |
| 287 MergeToFieldMask(current_path, it->second, out); | 268 MergeToFieldMask(current_path, it->second, out); |
| 288 } | 269 } |
| 289 } | 270 } |
| 290 | 271 |
| 291 void FieldMaskTree::AddPath(const string& path) { | 272 void FieldMaskTree::AddPath(const string& path) { |
| 292 std::vector<string> parts = Split(path, "."); | 273 vector<string> parts = Split(path, "."); |
| 293 if (parts.empty()) { | 274 if (parts.empty()) { |
| 294 return; | 275 return; |
| 295 } | 276 } |
| 296 bool new_branch = false; | 277 bool new_branch = false; |
| 297 Node* node = &root_; | 278 Node* node = &root_; |
| 298 for (int i = 0; i < parts.size(); ++i) { | 279 for (int i = 0; i < parts.size(); ++i) { |
| 299 if (!new_branch && node != &root_ && node->children.empty()) { | 280 if (!new_branch && node != &root_ && node->children.empty()) { |
| 300 // Path matches an existing leaf node. This means the path is already | 281 // Path matches an existing leaf node. This means the path is already |
| 301 // coverred by this tree (for example, adding "foo.bar.baz" to a tree | 282 // coverred by this tree (for example, adding "foo.bar.baz" to a tree |
| 302 // which already contains "foo.bar"). | 283 // which already contains "foo.bar"). |
| 303 return; | 284 return; |
| 304 } | 285 } |
| 305 const string& node_name = parts[i]; | 286 const string& node_name = parts[i]; |
| 306 Node*& child = node->children[node_name]; | 287 Node*& child = node->children[node_name]; |
| 307 if (child == NULL) { | 288 if (child == NULL) { |
| 308 new_branch = true; | 289 new_branch = true; |
| 309 child = new Node(); | 290 child = new Node(); |
| 310 } | 291 } |
| 311 node = child; | 292 node = child; |
| 312 } | 293 } |
| 313 if (!node->children.empty()) { | 294 if (!node->children.empty()) { |
| 314 node->ClearChildren(); | 295 node->ClearChildren(); |
| 315 } | 296 } |
| 316 } | 297 } |
| 317 | 298 |
| 318 void FieldMaskTree::IntersectPath(const string& path, FieldMaskTree* out) { | 299 void FieldMaskTree::IntersectPath(const string& path, FieldMaskTree* out) { |
| 319 std::vector<string> parts = Split(path, "."); | 300 vector<string> parts = Split(path, "."); |
| 320 if (parts.empty()) { | 301 if (parts.empty()) { |
| 321 return; | 302 return; |
| 322 } | 303 } |
| 323 const Node* node = &root_; | 304 const Node* node = &root_; |
| 324 for (int i = 0; i < parts.size(); ++i) { | 305 for (int i = 0; i < parts.size(); ++i) { |
| 325 if (node->children.empty()) { | 306 if (node->children.empty()) { |
| 326 if (node != &root_) { | 307 if (node != &root_) { |
| 327 out->AddPath(path); | 308 out->AddPath(path); |
| 328 } | 309 } |
| 329 return; | 310 return; |
| 330 } | 311 } |
| 331 const string& node_name = parts[i]; | 312 const string& node_name = parts[i]; |
| 332 const Node* result = FindPtrOrNull(node->children, node_name); | 313 const Node* result = FindPtrOrNull(node->children, node_name); |
| 333 if (result == NULL) { | 314 if (result == NULL) { |
| 334 // No intersection found. | 315 // No intersection found. |
| 335 return; | 316 return; |
| 336 } | 317 } |
| 337 node = result; | 318 node = result; |
| 338 } | 319 } |
| 339 // Now we found a matching node with the given path. Add all leaf nodes | 320 // Now we found a matching node with the given path. Add all leaf nodes |
| 340 // to out. | 321 // to out. |
| 341 MergeLeafNodesToTree(path, node, out); | 322 MergeLeafNodesToTree(path, node, out); |
| 342 } | 323 } |
| 343 | 324 |
| 344 void FieldMaskTree::MergeLeafNodesToTree(const string& prefix, const Node* node, | 325 void FieldMaskTree::MergeLeafNodesToTree(const string& prefix, const Node* node, |
| 345 FieldMaskTree* out) { | 326 FieldMaskTree* out) { |
| 346 if (node->children.empty()) { | 327 if (node->children.empty()) { |
| 347 out->AddPath(prefix); | 328 out->AddPath(prefix); |
| 348 } | 329 } |
| 349 for (std::map<string, Node*>::const_iterator it = node->children.begin(); | 330 for (map<string, Node*>::const_iterator it = node->children.begin(); |
| 350 it != node->children.end(); ++it) { | 331 it != node->children.end(); ++it) { |
| 351 string current_path = prefix.empty() ? it->first : prefix + "." + it->first; | 332 string current_path = prefix.empty() ? it->first : prefix + "." + it->first; |
| 352 MergeLeafNodesToTree(current_path, it->second, out); | 333 MergeLeafNodesToTree(current_path, it->second, out); |
| 353 } | 334 } |
| 354 } | 335 } |
| 355 | 336 |
| 356 void FieldMaskTree::MergeMessage(const Node* node, const Message& source, | 337 void FieldMaskTree::MergeMessage(const Node* node, const Message& source, |
| 357 const FieldMaskUtil::MergeOptions& options, | 338 const FieldMaskUtil::MergeOptions& options, |
| 358 Message* destination) { | 339 Message* destination) { |
| 359 GOOGLE_DCHECK(!node->children.empty()); | 340 GOOGLE_DCHECK(!node->children.empty()); |
| 360 const Reflection* source_reflection = source.GetReflection(); | 341 const Reflection* source_reflection = source.GetReflection(); |
| 361 const Reflection* destination_reflection = destination->GetReflection(); | 342 const Reflection* destination_reflection = destination->GetReflection(); |
| 362 const Descriptor* descriptor = source.GetDescriptor(); | 343 const Descriptor* descriptor = source.GetDescriptor(); |
| 363 for (std::map<string, Node*>::const_iterator it = node->children.begin(); | 344 for (map<string, Node*>::const_iterator it = node->children.begin(); |
| 364 it != node->children.end(); ++it) { | 345 it != node->children.end(); ++it) { |
| 365 const string& field_name = it->first; | 346 const string& field_name = it->first; |
| 366 const Node* child = it->second; | 347 const Node* child = it->second; |
| 367 const FieldDescriptor* field = descriptor->FindFieldByName(field_name); | 348 const FieldDescriptor* field = descriptor->FindFieldByName(field_name); |
| 368 if (field == NULL) { | 349 if (field == NULL) { |
| 369 GOOGLE_LOG(ERROR) << "Cannot find field \"" << field_name << "\" in messag
e " | 350 GOOGLE_LOG(ERROR) << "Cannot find field \"" << field_name << "\" in messag
e " |
| 370 << descriptor->full_name(); | 351 << descriptor->full_name(); |
| 371 continue; | 352 continue; |
| 372 } | 353 } |
| 373 if (!child->children.empty()) { | 354 if (!child->children.empty()) { |
| 374 // Sub-paths are only allowed for singular message fields. | 355 // Sub-paths are only allowed for singular message fields. |
| 375 if (field->is_repeated() || | 356 if (field->is_repeated() || |
| 376 field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { | 357 field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { |
| 377 GOOGLE_LOG(ERROR) << "Field \"" << field_name << "\" in message " | 358 GOOGLE_LOG(ERROR) << "Field \"" << field_name << "\" in message " |
| 378 << descriptor->full_name() | 359 << descriptor->full_name() |
| 379 << " is not a singular message field and cannot " | 360 << " is not a singular message field and cannot " |
| 380 << "have sub-fields."; | 361 << "have sub-fields."; |
| 381 continue; | 362 continue; |
| 382 } | 363 } |
| 383 MergeMessage(child, source_reflection->GetMessage(source, field), options, | 364 MergeMessage(child, source_reflection->GetMessage(source, field), options, |
| 384 destination_reflection->MutableMessage(destination, field)); | 365 destination_reflection->MutableMessage(destination, field)); |
| 385 continue; | 366 continue; |
| 386 } | 367 } |
| 387 if (!field->is_repeated()) { | 368 if (!field->is_repeated()) { |
| 388 switch (field->cpp_type()) { | 369 switch (field->cpp_type()) { |
| 389 #define COPY_VALUE(TYPE, Name) \ | 370 #define COPY_VALUE(TYPE, Name) \ |
| 390 case FieldDescriptor::CPPTYPE_##TYPE: { \ | 371 case FieldDescriptor::CPPTYPE_##TYPE: { \ |
| 391 if (source_reflection->HasField(source, field)) { \ | 372 destination_reflection->Set##Name( \ |
| 392 destination_reflection->Set##Name( \ | 373 destination, field, source_reflection->Get##Name(source, field)); \ |
| 393 destination, field, source_reflection->Get##Name(source, field)); \ | 374 break; \ |
| 394 } else { \ | |
| 395 destination_reflection->ClearField(destination, field); \ | |
| 396 } \ | |
| 397 break; \ | |
| 398 } | 375 } |
| 399 COPY_VALUE(BOOL, Bool) | 376 COPY_VALUE(BOOL, Bool) |
| 400 COPY_VALUE(INT32, Int32) | 377 COPY_VALUE(INT32, Int32) |
| 401 COPY_VALUE(INT64, Int64) | 378 COPY_VALUE(INT64, Int64) |
| 402 COPY_VALUE(UINT32, UInt32) | 379 COPY_VALUE(UINT32, UInt32) |
| 403 COPY_VALUE(UINT64, UInt64) | 380 COPY_VALUE(UINT64, UInt64) |
| 404 COPY_VALUE(FLOAT, Float) | 381 COPY_VALUE(FLOAT, Float) |
| 405 COPY_VALUE(DOUBLE, Double) | 382 COPY_VALUE(DOUBLE, Double) |
| 406 COPY_VALUE(ENUM, Enum) | 383 COPY_VALUE(ENUM, Enum) |
| 407 COPY_VALUE(STRING, String) | 384 COPY_VALUE(STRING, String) |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 ->MergeFrom( | 426 ->MergeFrom( |
| 450 source_reflection->GetRepeatedMessage(source, field, i)); | 427 source_reflection->GetRepeatedMessage(source, field, i)); |
| 451 } | 428 } |
| 452 break; | 429 break; |
| 453 } | 430 } |
| 454 } | 431 } |
| 455 } | 432 } |
| 456 } | 433 } |
| 457 } | 434 } |
| 458 | 435 |
| 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 | |
| 480 } // namespace | 436 } // namespace |
| 481 | 437 |
| 482 void FieldMaskUtil::ToCanonicalForm(const FieldMask& mask, FieldMask* out) { | 438 void FieldMaskUtil::ToCanonicalForm(const FieldMask& mask, FieldMask* out) { |
| 483 FieldMaskTree tree; | 439 FieldMaskTree tree; |
| 484 tree.MergeFromFieldMask(mask); | 440 tree.MergeFromFieldMask(mask); |
| 485 out->Clear(); | 441 out->Clear(); |
| 486 tree.MergeToFieldMask(out); | 442 tree.MergeToFieldMask(out); |
| 487 } | 443 } |
| 488 | 444 |
| 489 void FieldMaskUtil::Union(const FieldMask& mask1, const FieldMask& mask2, | 445 void FieldMaskUtil::Union(const FieldMask& mask1, const FieldMask& mask2, |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 526 const MergeOptions& options, | 482 const MergeOptions& options, |
| 527 Message* destination) { | 483 Message* destination) { |
| 528 GOOGLE_CHECK(source.GetDescriptor() == destination->GetDescriptor()); | 484 GOOGLE_CHECK(source.GetDescriptor() == destination->GetDescriptor()); |
| 529 // Build a FieldMaskTree and walk through the tree to merge all specified | 485 // Build a FieldMaskTree and walk through the tree to merge all specified |
| 530 // fields. | 486 // fields. |
| 531 FieldMaskTree tree; | 487 FieldMaskTree tree; |
| 532 tree.MergeFromFieldMask(mask); | 488 tree.MergeFromFieldMask(mask); |
| 533 tree.MergeMessage(source, options, destination); | 489 tree.MergeMessage(source, options, destination); |
| 534 } | 490 } |
| 535 | 491 |
| 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 | |
| 544 } // namespace util | 492 } // namespace util |
| 545 } // namespace protobuf | 493 } // namespace protobuf |
| 546 } // namespace google | 494 } // namespace google |
| OLD | NEW |