| 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 } // namespace | 57 } // namespace |
| 58 | 58 |
| 59 DefaultValueObjectWriter::DefaultValueObjectWriter( | 59 DefaultValueObjectWriter::DefaultValueObjectWriter( |
| 60 TypeResolver* type_resolver, const google::protobuf::Type& type, | 60 TypeResolver* type_resolver, const google::protobuf::Type& type, |
| 61 ObjectWriter* ow) | 61 ObjectWriter* ow) |
| 62 : typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), | 62 : typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), |
| 63 own_typeinfo_(true), | 63 own_typeinfo_(true), |
| 64 type_(type), | 64 type_(type), |
| 65 current_(NULL), | 65 current_(NULL), |
| 66 root_(NULL), | 66 root_(NULL), |
| 67 suppress_empty_list_(false), | |
| 68 field_scrub_callback_(NULL), | 67 field_scrub_callback_(NULL), |
| 69 ow_(ow) {} | 68 ow_(ow) {} |
| 70 | 69 |
| 71 DefaultValueObjectWriter::~DefaultValueObjectWriter() { | 70 DefaultValueObjectWriter::~DefaultValueObjectWriter() { |
| 72 for (int i = 0; i < string_values_.size(); ++i) { | 71 for (int i = 0; i < string_values_.size(); ++i) { |
| 73 delete string_values_[i]; | 72 delete string_values_[i]; |
| 74 } | 73 } |
| 75 if (own_typeinfo_) { | 74 if (own_typeinfo_) { |
| 76 delete typeinfo_; | 75 delete typeinfo_; |
| 77 } | 76 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 RenderDataPiece(name, DataPiece(*string_values_.back(), true)); | 157 RenderDataPiece(name, DataPiece(*string_values_.back(), true)); |
| 159 } | 158 } |
| 160 return this; | 159 return this; |
| 161 } | 160 } |
| 162 | 161 |
| 163 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes( | 162 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes( |
| 164 StringPiece name, StringPiece value) { | 163 StringPiece name, StringPiece value) { |
| 165 if (current_ == NULL) { | 164 if (current_ == NULL) { |
| 166 ow_->RenderBytes(name, value); | 165 ow_->RenderBytes(name, value); |
| 167 } else { | 166 } else { |
| 168 // Since StringPiece is essentially a pointer, takes a copy of "value" to | 167 RenderDataPiece(name, DataPiece(value, false, true)); |
| 169 // avoid ownership issues. | |
| 170 string_values_.push_back(new string(value.ToString())); | |
| 171 RenderDataPiece(name, DataPiece(*string_values_.back(), false, true)); | |
| 172 } | 168 } |
| 173 return this; | 169 return this; |
| 174 } | 170 } |
| 175 | 171 |
| 176 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderNull( | 172 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderNull( |
| 177 StringPiece name) { | 173 StringPiece name) { |
| 178 if (current_ == NULL) { | 174 if (current_ == NULL) { |
| 179 ow_->RenderNull(name); | 175 ow_->RenderNull(name); |
| 180 } else { | 176 } else { |
| 181 RenderDataPiece(name, DataPiece::NullData()); | 177 RenderDataPiece(name, DataPiece::NullData()); |
| 182 } | 178 } |
| 183 return this; | 179 return this; |
| 184 } | 180 } |
| 185 | 181 |
| 186 void DefaultValueObjectWriter::RegisterFieldScrubCallBack( | 182 void DefaultValueObjectWriter::RegisterFieldScrubCallBack( |
| 187 FieldScrubCallBackPtr field_scrub_callback) { | 183 FieldScrubCallBackPtr field_scrub_callback) { |
| 188 field_scrub_callback_.reset(field_scrub_callback.release()); | 184 field_scrub_callback_.reset(field_scrub_callback.release()); |
| 189 } | 185 } |
| 190 | 186 |
| 191 DefaultValueObjectWriter::Node::Node( | 187 DefaultValueObjectWriter::Node::Node(const string& name, |
| 192 const string& name, const google::protobuf::Type* type, NodeKind kind, | 188 const google::protobuf::Type* type, |
| 193 const DataPiece& data, bool is_placeholder, const std::vector<string>& path, | 189 NodeKind kind, const DataPiece& data, |
| 194 bool suppress_empty_list, FieldScrubCallBack* field_scrub_callback) | 190 bool is_placeholder, |
| 191 const vector<string>& path, |
| 192 FieldScrubCallBack* field_scrub_callback) |
| 195 : name_(name), | 193 : name_(name), |
| 196 type_(type), | 194 type_(type), |
| 197 kind_(kind), | 195 kind_(kind), |
| 198 is_any_(false), | 196 is_any_(false), |
| 199 data_(data), | 197 data_(data), |
| 200 is_placeholder_(is_placeholder), | 198 is_placeholder_(is_placeholder), |
| 201 path_(path), | 199 path_(path), |
| 202 suppress_empty_list_(suppress_empty_list), | |
| 203 field_scrub_callback_(field_scrub_callback) {} | 200 field_scrub_callback_(field_scrub_callback) {} |
| 204 | 201 |
| 205 DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild( | 202 DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild( |
| 206 StringPiece name) { | 203 StringPiece name) { |
| 207 if (name.empty() || kind_ != OBJECT) { | 204 if (name.empty() || kind_ != OBJECT) { |
| 208 return NULL; | 205 return NULL; |
| 209 } | 206 } |
| 210 for (int i = 0; i < children_.size(); ++i) { | 207 for (int i = 0; i < children_.size(); ++i) { |
| 211 Node* child = children_[i]; | 208 Node* child = children_[i]; |
| 212 if (child->name() == name) { | 209 if (child->name() == name) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 226 if (kind_ == MAP) { | 223 if (kind_ == MAP) { |
| 227 ow->StartObject(name_); | 224 ow->StartObject(name_); |
| 228 WriteChildren(ow); | 225 WriteChildren(ow); |
| 229 ow->EndObject(); | 226 ow->EndObject(); |
| 230 return; | 227 return; |
| 231 } | 228 } |
| 232 | 229 |
| 233 // Write out lists. If we didn't have any list in response, write out empty | 230 // Write out lists. If we didn't have any list in response, write out empty |
| 234 // list. | 231 // list. |
| 235 if (kind_ == LIST) { | 232 if (kind_ == LIST) { |
| 236 // Suppress empty lists if requested. | |
| 237 if (suppress_empty_list_ && is_placeholder_) return; | |
| 238 | |
| 239 ow->StartList(name_); | 233 ow->StartList(name_); |
| 240 WriteChildren(ow); | 234 WriteChildren(ow); |
| 241 ow->EndList(); | 235 ow->EndList(); |
| 242 return; | 236 return; |
| 243 } | 237 } |
| 244 | 238 |
| 245 // If is_placeholder_ = true, we didn't see this node in the response, so | 239 // If is_placeholder_ = true, we didn't see this node in the response, so |
| 246 // skip output. | 240 // skip output. |
| 247 if (is_placeholder_) return; | 241 if (is_placeholder_) return; |
| 248 | 242 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 // Creates a map of child nodes to speed up lookup. | 297 // Creates a map of child nodes to speed up lookup. |
| 304 for (int i = 0; i < children_.size(); ++i) { | 298 for (int i = 0; i < children_.size(); ++i) { |
| 305 InsertIfNotPresent(&orig_children_map, children_[i]->name_, i); | 299 InsertIfNotPresent(&orig_children_map, children_[i]->name_, i); |
| 306 } | 300 } |
| 307 | 301 |
| 308 for (int i = 0; i < type_->fields_size(); ++i) { | 302 for (int i = 0; i < type_->fields_size(); ++i) { |
| 309 const google::protobuf::Field& field = type_->fields(i); | 303 const google::protobuf::Field& field = type_->fields(i); |
| 310 | 304 |
| 311 // This code is checking if the field to be added to the tree should be | 305 // This code is checking if the field to be added to the tree should be |
| 312 // scrubbed or not by calling the field_scrub_callback_ callback function. | 306 // scrubbed or not by calling the field_scrub_callback_ callback function. |
| 313 std::vector<string> path; | 307 vector<string> path; |
| 314 if (!path_.empty()) { | 308 if (!path_.empty()) { |
| 315 path.insert(path.begin(), path_.begin(), path_.end()); | 309 path.insert(path.begin(), path_.begin(), path_.end()); |
| 316 } | 310 } |
| 317 path.push_back(field.name()); | 311 path.push_back(field.name()); |
| 318 if (field_scrub_callback_ != NULL && | 312 if (field_scrub_callback_ != NULL && |
| 319 field_scrub_callback_->Run(path, &field)) { | 313 field_scrub_callback_->Run(path, &field)) { |
| 320 continue; | 314 continue; |
| 321 } | 315 } |
| 322 | 316 |
| 323 hash_map<string, int>::iterator found = | 317 hash_map<string, int>::iterator found = |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 // If oneof_index() != 0, the child field is part of a "oneof", which means | 359 // If oneof_index() != 0, the child field is part of a "oneof", which means |
| 366 // the child field is optional and we shouldn't populate its default value. | 360 // the child field is optional and we shouldn't populate its default value. |
| 367 if (field.oneof_index() != 0) continue; | 361 if (field.oneof_index() != 0) continue; |
| 368 | 362 |
| 369 // If the child field is of primitive type, sets its data to the default | 363 // If the child field is of primitive type, sets its data to the default |
| 370 // value of its type. | 364 // value of its type. |
| 371 google::protobuf::scoped_ptr<Node> child(new Node( | 365 google::protobuf::scoped_ptr<Node> child(new Node( |
| 372 field.json_name(), field_type, kind, | 366 field.json_name(), field_type, kind, |
| 373 kind == PRIMITIVE ? CreateDefaultDataPieceForField(field, typeinfo) | 367 kind == PRIMITIVE ? CreateDefaultDataPieceForField(field, typeinfo) |
| 374 : DataPiece::NullData(), | 368 : DataPiece::NullData(), |
| 375 true, path, suppress_empty_list_, field_scrub_callback_)); | 369 true, path, field_scrub_callback_)); |
| 376 new_children.push_back(child.release()); | 370 new_children.push_back(child.release()); |
| 377 } | 371 } |
| 378 // Adds all leftover nodes in children_ to the beginning of new_child. | 372 // Adds all leftover nodes in children_ to the beginning of new_child. |
| 379 for (int i = 0; i < children_.size(); ++i) { | 373 for (int i = 0; i < children_.size(); ++i) { |
| 380 if (children_[i] == NULL) { | 374 if (children_[i] == NULL) { |
| 381 continue; | 375 continue; |
| 382 } | 376 } |
| 383 new_children.insert(new_children.begin(), children_[i]); | 377 new_children.insert(new_children.begin(), children_[i]); |
| 384 children_[i] = NULL; | 378 children_[i] = NULL; |
| 385 } | 379 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 459 case google::protobuf::Field_Kind_TYPE_ENUM: { | 453 case google::protobuf::Field_Kind_TYPE_ENUM: { |
| 460 return FindEnumDefault(field, typeinfo); | 454 return FindEnumDefault(field, typeinfo); |
| 461 } | 455 } |
| 462 default: { return DataPiece::NullData(); } | 456 default: { return DataPiece::NullData(); } |
| 463 } | 457 } |
| 464 } | 458 } |
| 465 | 459 |
| 466 DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject( | 460 DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject( |
| 467 StringPiece name) { | 461 StringPiece name) { |
| 468 if (current_ == NULL) { | 462 if (current_ == NULL) { |
| 469 std::vector<string> path; | 463 vector<string> path; |
| 470 root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(), | 464 root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(), |
| 471 false, path, suppress_empty_list_, | 465 false, path, field_scrub_callback_.get())); |
| 472 field_scrub_callback_.get())); | |
| 473 root_->PopulateChildren(typeinfo_); | 466 root_->PopulateChildren(typeinfo_); |
| 474 current_ = root_.get(); | 467 current_ = root_.get(); |
| 475 return this; | 468 return this; |
| 476 } | 469 } |
| 477 MaybePopulateChildrenOfAny(current_); | 470 MaybePopulateChildrenOfAny(current_); |
| 478 Node* child = current_->FindChild(name); | 471 Node* child = current_->FindChild(name); |
| 479 if (current_->kind() == LIST || current_->kind() == MAP || child == NULL) { | 472 if (current_->kind() == LIST || current_->kind() == MAP || child == NULL) { |
| 480 // If current_ is a list or a map node, we should create a new child and use | 473 // If current_ is a list or a map node, we should create a new child and use |
| 481 // the type of current_ as the type of the new child. | 474 // the type of current_ as the type of the new child. |
| 482 google::protobuf::scoped_ptr<Node> node(new Node( | 475 google::protobuf::scoped_ptr<Node> node(new Node( |
| 483 name.ToString(), ((current_->kind() == LIST || current_->kind() == MAP) | 476 name.ToString(), ((current_->kind() == LIST || current_->kind() == MAP) |
| 484 ? current_->type() | 477 ? current_->type() |
| 485 : NULL), | 478 : NULL), |
| 486 OBJECT, DataPiece::NullData(), false, | 479 OBJECT, DataPiece::NullData(), false, |
| 487 child == NULL ? current_->path() : child->path(), | 480 child == NULL ? current_->path() : child->path(), |
| 488 suppress_empty_list_, field_scrub_callback_.get())); | 481 field_scrub_callback_.get())); |
| 489 child = node.get(); | 482 child = node.get(); |
| 490 current_->AddChild(node.release()); | 483 current_->AddChild(node.release()); |
| 491 } | 484 } |
| 492 | 485 |
| 493 child->set_is_placeholder(false); | 486 child->set_is_placeholder(false); |
| 494 if (child->kind() == OBJECT && child->number_of_children() == 0) { | 487 if (child->kind() == OBJECT && child->number_of_children() == 0) { |
| 495 child->PopulateChildren(typeinfo_); | 488 child->PopulateChildren(typeinfo_); |
| 496 } | 489 } |
| 497 | 490 |
| 498 stack_.push(current_); | 491 stack_.push(current_); |
| 499 current_ = child; | 492 current_ = child; |
| 500 return this; | 493 return this; |
| 501 } | 494 } |
| 502 | 495 |
| 503 DefaultValueObjectWriter* DefaultValueObjectWriter::EndObject() { | 496 DefaultValueObjectWriter* DefaultValueObjectWriter::EndObject() { |
| 504 if (stack_.empty()) { | 497 if (stack_.empty()) { |
| 505 // The root object ends here. Writes out the tree. | 498 // The root object ends here. Writes out the tree. |
| 506 WriteRoot(); | 499 WriteRoot(); |
| 507 return this; | 500 return this; |
| 508 } | 501 } |
| 509 current_ = stack_.top(); | 502 current_ = stack_.top(); |
| 510 stack_.pop(); | 503 stack_.pop(); |
| 511 return this; | 504 return this; |
| 512 } | 505 } |
| 513 | 506 |
| 514 DefaultValueObjectWriter* DefaultValueObjectWriter::StartList( | 507 DefaultValueObjectWriter* DefaultValueObjectWriter::StartList( |
| 515 StringPiece name) { | 508 StringPiece name) { |
| 516 if (current_ == NULL) { | 509 if (current_ == NULL) { |
| 517 std::vector<string> path; | 510 vector<string> path; |
| 518 root_.reset(new Node(name.ToString(), &type_, LIST, DataPiece::NullData(), | 511 root_.reset(new Node(name.ToString(), &type_, LIST, DataPiece::NullData(), |
| 519 false, path, suppress_empty_list_, | 512 false, path, field_scrub_callback_.get())); |
| 520 field_scrub_callback_.get())); | |
| 521 current_ = root_.get(); | 513 current_ = root_.get(); |
| 522 return this; | 514 return this; |
| 523 } | 515 } |
| 524 MaybePopulateChildrenOfAny(current_); | 516 MaybePopulateChildrenOfAny(current_); |
| 525 Node* child = current_->FindChild(name); | 517 Node* child = current_->FindChild(name); |
| 526 if (child == NULL || child->kind() != LIST) { | 518 if (child == NULL || child->kind() != LIST) { |
| 527 google::protobuf::scoped_ptr<Node> node( | 519 google::protobuf::scoped_ptr<Node> node( |
| 528 new Node(name.ToString(), NULL, LIST, DataPiece::NullData(), false, | 520 new Node(name.ToString(), NULL, LIST, DataPiece::NullData(), false, |
| 529 child == NULL ? current_->path() : child->path(), | 521 child == NULL ? current_->path() : child->path(), |
| 530 suppress_empty_list_, field_scrub_callback_.get())); | 522 field_scrub_callback_.get())); |
| 531 child = node.get(); | 523 child = node.get(); |
| 532 current_->AddChild(node.release()); | 524 current_->AddChild(node.release()); |
| 533 } | 525 } |
| 534 child->set_is_placeholder(false); | 526 child->set_is_placeholder(false); |
| 535 | 527 |
| 536 stack_.push(current_); | 528 stack_.push(current_); |
| 537 current_ = child; | 529 current_ = child; |
| 538 return this; | 530 return this; |
| 539 } | 531 } |
| 540 | 532 |
| 541 void DefaultValueObjectWriter::WriteRoot() { | 533 void DefaultValueObjectWriter::WriteRoot() { |
| 542 root_->WriteTo(ow_); | 534 root_->WriteTo(ow_); |
| 543 root_.reset(NULL); | 535 root_.reset(NULL); |
| 544 current_ = NULL; | 536 current_ = NULL; |
| 545 } | 537 } |
| 546 | 538 |
| 547 DefaultValueObjectWriter* DefaultValueObjectWriter::EndList() { | 539 DefaultValueObjectWriter* DefaultValueObjectWriter::EndList() { |
| 548 if (stack_.empty()) { | 540 if (stack_.empty()) { |
| 549 WriteRoot(); | 541 WriteRoot(); |
| 550 return this; | 542 return this; |
| 551 } | 543 } |
| 552 current_ = stack_.top(); | 544 current_ = stack_.top(); |
| 553 stack_.pop(); | 545 stack_.pop(); |
| 554 return this; | 546 return this; |
| 555 } | 547 } |
| 556 | 548 |
| 557 void DefaultValueObjectWriter::RenderDataPiece(StringPiece name, | 549 void DefaultValueObjectWriter::RenderDataPiece(StringPiece name, |
| 558 const DataPiece& data) { | 550 const DataPiece& data) { |
| 559 MaybePopulateChildrenOfAny(current_); | 551 MaybePopulateChildrenOfAny(current_); |
| 552 util::StatusOr<string> data_string = data.ToString(); |
| 560 if (current_->type() != NULL && current_->type()->name() == kAnyType && | 553 if (current_->type() != NULL && current_->type()->name() == kAnyType && |
| 561 name == "@type") { | 554 name == "@type" && data_string.ok()) { |
| 562 util::StatusOr<string> data_string = data.ToString(); | 555 const string& string_value = data_string.ValueOrDie(); |
| 563 if (data_string.ok()) { | 556 // If the type of current_ is "Any" and its "@type" field is being set here, |
| 564 const string& string_value = data_string.ValueOrDie(); | 557 // sets the type of current_ to be the type specified by the "@type". |
| 565 // If the type of current_ is "Any" and its "@type" field is being set | 558 util::StatusOr<const google::protobuf::Type*> found_type = |
| 566 // here, sets the type of current_ to be the type specified by the | 559 typeinfo_->ResolveTypeUrl(string_value); |
| 567 // "@type". | 560 if (!found_type.ok()) { |
| 568 util::StatusOr<const google::protobuf::Type*> found_type = | 561 GOOGLE_LOG(WARNING) << "Failed to resolve type '" << string_value << "'."; |
| 569 typeinfo_->ResolveTypeUrl(string_value); | 562 } else { |
| 570 if (!found_type.ok()) { | 563 current_->set_type(found_type.ValueOrDie()); |
| 571 GOOGLE_LOG(WARNING) << "Failed to resolve type '" << string_value << "'.
"; | 564 } |
| 572 } else { | 565 current_->set_is_any(true); |
| 573 current_->set_type(found_type.ValueOrDie()); | 566 // If the "@type" field is placed after other fields, we should populate |
| 574 } | 567 // other children of primitive type now. Otherwise, we should wait until the |
| 575 current_->set_is_any(true); | 568 // first value field is rendered before we populate the children, because |
| 576 // If the "@type" field is placed after other fields, we should populate | 569 // the "value" field of a Any message could be omitted. |
| 577 // other children of primitive type now. Otherwise, we should wait until | 570 if (current_->number_of_children() > 1 && current_->type() != NULL) { |
| 578 // the first value field is rendered before we populate the children, | 571 current_->PopulateChildren(typeinfo_); |
| 579 // because the "value" field of a Any message could be omitted. | |
| 580 if (current_->number_of_children() > 1 && current_->type() != NULL) { | |
| 581 current_->PopulateChildren(typeinfo_); | |
| 582 } | |
| 583 } | 572 } |
| 584 } | 573 } |
| 585 Node* child = current_->FindChild(name); | 574 Node* child = current_->FindChild(name); |
| 586 if (child == NULL || child->kind() != PRIMITIVE) { | 575 if (child == NULL || child->kind() != PRIMITIVE) { |
| 587 // No children are found, creates a new child. | 576 // No children are found, creates a new child. |
| 588 google::protobuf::scoped_ptr<Node> node( | 577 google::protobuf::scoped_ptr<Node> node( |
| 589 new Node(name.ToString(), NULL, PRIMITIVE, data, false, | 578 new Node(name.ToString(), NULL, PRIMITIVE, data, false, |
| 590 child == NULL ? current_->path() : child->path(), | 579 child == NULL ? current_->path() : child->path(), |
| 591 suppress_empty_list_, field_scrub_callback_.get())); | 580 field_scrub_callback_.get())); |
| 581 child = node.get(); |
| 592 current_->AddChild(node.release()); | 582 current_->AddChild(node.release()); |
| 593 } else { | 583 } else { |
| 594 child->set_data(data); | 584 child->set_data(data); |
| 595 } | 585 } |
| 596 } | 586 } |
| 597 | 587 |
| 598 } // namespace converter | 588 } // namespace converter |
| 599 } // namespace util | 589 } // namespace util |
| 600 } // namespace protobuf | 590 } // namespace protobuf |
| 601 } // namespace google | 591 } // namespace google |
| OLD | NEW |