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