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 |