| 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 // http://code.google.com/p/protobuf/ | 3 // http://code.google.com/p/protobuf/ |
| 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 #include <google/protobuf/text_format.h> | 42 #include <google/protobuf/text_format.h> |
| 43 | 43 |
| 44 #include <google/protobuf/descriptor.h> | 44 #include <google/protobuf/descriptor.h> |
| 45 #include <google/protobuf/io/coded_stream.h> | 45 #include <google/protobuf/io/coded_stream.h> |
| 46 #include <google/protobuf/io/zero_copy_stream.h> | 46 #include <google/protobuf/io/zero_copy_stream.h> |
| 47 #include <google/protobuf/io/zero_copy_stream_impl.h> | 47 #include <google/protobuf/io/zero_copy_stream_impl.h> |
| 48 #include <google/protobuf/unknown_field_set.h> | 48 #include <google/protobuf/unknown_field_set.h> |
| 49 #include <google/protobuf/descriptor.pb.h> | 49 #include <google/protobuf/descriptor.pb.h> |
| 50 #include <google/protobuf/io/tokenizer.h> | 50 #include <google/protobuf/io/tokenizer.h> |
| 51 #include <google/protobuf/stubs/strutil.h> | 51 #include <google/protobuf/stubs/strutil.h> |
| 52 #include <google/protobuf/stubs/map-util.h> |
| 53 #include <google/protobuf/stubs/stl_util.h> |
| 52 | 54 |
| 53 namespace google { | 55 namespace google { |
| 54 namespace protobuf { | 56 namespace protobuf { |
| 55 | 57 |
| 56 string Message::DebugString() const { | 58 string Message::DebugString() const { |
| 57 string debug_string; | 59 string debug_string; |
| 58 | 60 |
| 59 TextFormat::PrintToString(*this, &debug_string); | 61 TextFormat::PrintToString(*this, &debug_string); |
| 60 | 62 |
| 61 return debug_string; | 63 return debug_string; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 87 | 89 |
| 88 return debug_string; | 90 return debug_string; |
| 89 } | 91 } |
| 90 | 92 |
| 91 void Message::PrintDebugString() const { | 93 void Message::PrintDebugString() const { |
| 92 printf("%s", DebugString().c_str()); | 94 printf("%s", DebugString().c_str()); |
| 93 } | 95 } |
| 94 | 96 |
| 95 | 97 |
| 96 // =========================================================================== | 98 // =========================================================================== |
| 99 // Implementation of the parse information tree class. |
| 100 TextFormat::ParseInfoTree::ParseInfoTree() { } |
| 101 |
| 102 TextFormat::ParseInfoTree::~ParseInfoTree() { |
| 103 // Remove any nested information trees, as they are owned by this tree. |
| 104 for (NestedMap::iterator it = nested_.begin(); it != nested_.end(); ++it) { |
| 105 STLDeleteElements(&(it->second)); |
| 106 } |
| 107 } |
| 108 |
| 109 void TextFormat::ParseInfoTree::RecordLocation( |
| 110 const FieldDescriptor* field, |
| 111 TextFormat::ParseLocation location) { |
| 112 locations_[field].push_back(location); |
| 113 } |
| 114 |
| 115 TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::CreateNested( |
| 116 const FieldDescriptor* field) { |
| 117 // Owned by us in the map. |
| 118 TextFormat::ParseInfoTree* instance = new TextFormat::ParseInfoTree(); |
| 119 vector<TextFormat::ParseInfoTree*>* trees = &nested_[field]; |
| 120 GOOGLE_CHECK(trees); |
| 121 trees->push_back(instance); |
| 122 return instance; |
| 123 } |
| 124 |
| 125 void CheckFieldIndex(const FieldDescriptor* field, int index) { |
| 126 if (field == NULL) { return; } |
| 127 |
| 128 if (field->is_repeated() && index == -1) { |
| 129 GOOGLE_LOG(DFATAL) << "Index must be in range of repeated field values. " |
| 130 << "Field: " << field->name(); |
| 131 } else if (!field->is_repeated() && index != -1) { |
| 132 GOOGLE_LOG(DFATAL) << "Index must be -1 for singular fields." |
| 133 << "Field: " << field->name(); |
| 134 } |
| 135 } |
| 136 |
| 137 TextFormat::ParseLocation TextFormat::ParseInfoTree::GetLocation( |
| 138 const FieldDescriptor* field, int index) const { |
| 139 CheckFieldIndex(field, index); |
| 140 if (index == -1) { index = 0; } |
| 141 |
| 142 const vector<TextFormat::ParseLocation>* locations = |
| 143 FindOrNull(locations_, field); |
| 144 if (locations == NULL || index >= locations->size()) { |
| 145 return TextFormat::ParseLocation(); |
| 146 } |
| 147 |
| 148 return (*locations)[index]; |
| 149 } |
| 150 |
| 151 TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::GetTreeForNested( |
| 152 const FieldDescriptor* field, int index) const { |
| 153 CheckFieldIndex(field, index); |
| 154 if (index == -1) { index = 0; } |
| 155 |
| 156 const vector<TextFormat::ParseInfoTree*>* trees = FindOrNull(nested_, field); |
| 157 if (trees == NULL || index >= trees->size()) { |
| 158 return NULL; |
| 159 } |
| 160 |
| 161 return (*trees)[index]; |
| 162 } |
| 163 |
| 164 |
| 165 // =========================================================================== |
| 97 // Internal class for parsing an ASCII representation of a Protocol Message. | 166 // Internal class for parsing an ASCII representation of a Protocol Message. |
| 98 // This class makes use of the Protocol Message compiler's tokenizer found | 167 // This class makes use of the Protocol Message compiler's tokenizer found |
| 99 // in //google/protobuf/io/tokenizer.h. Note that class's Parse | 168 // in //google/protobuf/io/tokenizer.h. Note that class's Parse |
| 100 // method is *not* thread-safe and should only be used in a single thread at | 169 // method is *not* thread-safe and should only be used in a single thread at |
| 101 // a time. | 170 // a time. |
| 102 | 171 |
| 103 // Makes code slightly more readable. The meaning of "DO(foo)" is | 172 // Makes code slightly more readable. The meaning of "DO(foo)" is |
| 104 // "Execute foo and fail if it fails.", where failure is indicated by | 173 // "Execute foo and fail if it fails.", where failure is indicated by |
| 105 // returning false. Borrowed from parser.cc (Thanks Kenton!). | 174 // returning false. Borrowed from parser.cc (Thanks Kenton!). |
| 106 #define DO(STATEMENT) if (STATEMENT) {} else return false | 175 #define DO(STATEMENT) if (STATEMENT) {} else return false |
| 107 | 176 |
| 108 class TextFormat::Parser::ParserImpl { | 177 class TextFormat::Parser::ParserImpl { |
| 109 public: | 178 public: |
| 110 | 179 |
| 111 // Determines if repeated values for a non-repeated field are | 180 // Determines if repeated values for a non-repeated field are |
| 112 // permitted, e.g., the string "foo: 1 foo: 2" for a | 181 // permitted, e.g., the string "foo: 1 foo: 2" for a |
| 113 // required/optional field named "foo". | 182 // required/optional field named "foo". |
| 114 enum SingularOverwritePolicy { | 183 enum SingularOverwritePolicy { |
| 115 ALLOW_SINGULAR_OVERWRITES = 0, // the last value is retained | 184 ALLOW_SINGULAR_OVERWRITES = 0, // the last value is retained |
| 116 FORBID_SINGULAR_OVERWRITES = 1, // an error is issued | 185 FORBID_SINGULAR_OVERWRITES = 1, // an error is issued |
| 117 }; | 186 }; |
| 118 | 187 |
| 119 ParserImpl(const Descriptor* root_message_type, | 188 ParserImpl(const Descriptor* root_message_type, |
| 120 io::ZeroCopyInputStream* input_stream, | 189 io::ZeroCopyInputStream* input_stream, |
| 121 io::ErrorCollector* error_collector, | 190 io::ErrorCollector* error_collector, |
| 122 TextFormat::Finder* finder, | 191 TextFormat::Finder* finder, |
| 123 SingularOverwritePolicy singular_overwrite_policy) | 192 ParseInfoTree* parse_info_tree, |
| 193 SingularOverwritePolicy singular_overwrite_policy, |
| 194 bool allow_unknown_field) |
| 124 : error_collector_(error_collector), | 195 : error_collector_(error_collector), |
| 125 finder_(finder), | 196 finder_(finder), |
| 197 parse_info_tree_(parse_info_tree), |
| 126 tokenizer_error_collector_(this), | 198 tokenizer_error_collector_(this), |
| 127 tokenizer_(input_stream, &tokenizer_error_collector_), | 199 tokenizer_(input_stream, &tokenizer_error_collector_), |
| 128 root_message_type_(root_message_type), | 200 root_message_type_(root_message_type), |
| 129 singular_overwrite_policy_(singular_overwrite_policy), | 201 singular_overwrite_policy_(singular_overwrite_policy), |
| 202 allow_unknown_field_(allow_unknown_field), |
| 130 had_errors_(false) { | 203 had_errors_(false) { |
| 131 // For backwards-compatibility with proto1, we need to allow the 'f' suffix | 204 // For backwards-compatibility with proto1, we need to allow the 'f' suffix |
| 132 // for floats. | 205 // for floats. |
| 133 tokenizer_.set_allow_f_after_float(true); | 206 tokenizer_.set_allow_f_after_float(true); |
| 134 | 207 |
| 135 // '#' starts a comment. | 208 // '#' starts a comment. |
| 136 tokenizer_.set_comment_style(io::Tokenizer::SH_COMMENT_STYLE); | 209 tokenizer_.set_comment_style(io::Tokenizer::SH_COMMENT_STYLE); |
| 137 | 210 |
| 138 // Consume the starting token. | 211 // Consume the starting token. |
| 139 tokenizer_.Next(); | 212 tokenizer_.Next(); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 | 306 |
| 234 // Consumes the current field (as returned by the tokenizer) on the | 307 // Consumes the current field (as returned by the tokenizer) on the |
| 235 // passed in message. | 308 // passed in message. |
| 236 bool ConsumeField(Message* message) { | 309 bool ConsumeField(Message* message) { |
| 237 const Reflection* reflection = message->GetReflection(); | 310 const Reflection* reflection = message->GetReflection(); |
| 238 const Descriptor* descriptor = message->GetDescriptor(); | 311 const Descriptor* descriptor = message->GetDescriptor(); |
| 239 | 312 |
| 240 string field_name; | 313 string field_name; |
| 241 | 314 |
| 242 const FieldDescriptor* field = NULL; | 315 const FieldDescriptor* field = NULL; |
| 316 int start_line = tokenizer_.current().line; |
| 317 int start_column = tokenizer_.current().column; |
| 243 | 318 |
| 244 if (TryConsume("[")) { | 319 if (TryConsume("[")) { |
| 245 // Extension. | 320 // Extension. |
| 246 DO(ConsumeIdentifier(&field_name)); | 321 DO(ConsumeIdentifier(&field_name)); |
| 247 while (TryConsume(".")) { | 322 while (TryConsume(".")) { |
| 248 string part; | 323 string part; |
| 249 DO(ConsumeIdentifier(&part)); | 324 DO(ConsumeIdentifier(&part)); |
| 250 field_name += "."; | 325 field_name += "."; |
| 251 field_name += part; | 326 field_name += part; |
| 252 } | 327 } |
| 253 DO(Consume("]")); | 328 DO(Consume("]")); |
| 254 | 329 |
| 255 field = (finder_ != NULL | 330 field = (finder_ != NULL |
| 256 ? finder_->FindExtension(message, field_name) | 331 ? finder_->FindExtension(message, field_name) |
| 257 : reflection->FindKnownExtensionByName(field_name)); | 332 : reflection->FindKnownExtensionByName(field_name)); |
| 258 | 333 |
| 259 if (field == NULL) { | 334 if (field == NULL) { |
| 260 ReportError("Extension \"" + field_name + "\" is not defined or " | 335 if (!allow_unknown_field_) { |
| 261 "is not an extension of \"" + | 336 ReportError("Extension \"" + field_name + "\" is not defined or " |
| 262 descriptor->full_name() + "\"."); | 337 "is not an extension of \"" + |
| 263 return false; | 338 descriptor->full_name() + "\"."); |
| 339 return false; |
| 340 } else { |
| 341 ReportWarning("Extension \"" + field_name + "\" is not defined or " |
| 342 "is not an extension of \"" + |
| 343 descriptor->full_name() + "\"."); |
| 344 } |
| 264 } | 345 } |
| 265 } else { | 346 } else { |
| 266 DO(ConsumeIdentifier(&field_name)); | 347 DO(ConsumeIdentifier(&field_name)); |
| 267 | 348 |
| 268 field = descriptor->FindFieldByName(field_name); | 349 field = descriptor->FindFieldByName(field_name); |
| 269 // Group names are expected to be capitalized as they appear in the | 350 // Group names are expected to be capitalized as they appear in the |
| 270 // .proto file, which actually matches their type names, not their field | 351 // .proto file, which actually matches their type names, not their field |
| 271 // names. | 352 // names. |
| 272 if (field == NULL) { | 353 if (field == NULL) { |
| 273 string lower_field_name = field_name; | 354 string lower_field_name = field_name; |
| 274 LowerString(&lower_field_name); | 355 LowerString(&lower_field_name); |
| 275 field = descriptor->FindFieldByName(lower_field_name); | 356 field = descriptor->FindFieldByName(lower_field_name); |
| 276 // If the case-insensitive match worked but the field is NOT a group, | 357 // If the case-insensitive match worked but the field is NOT a group, |
| 277 if (field != NULL && field->type() != FieldDescriptor::TYPE_GROUP) { | 358 if (field != NULL && field->type() != FieldDescriptor::TYPE_GROUP) { |
| 278 field = NULL; | 359 field = NULL; |
| 279 } | 360 } |
| 280 } | 361 } |
| 281 // Again, special-case group names as described above. | 362 // Again, special-case group names as described above. |
| 282 if (field != NULL && field->type() == FieldDescriptor::TYPE_GROUP | 363 if (field != NULL && field->type() == FieldDescriptor::TYPE_GROUP |
| 283 && field->message_type()->name() != field_name) { | 364 && field->message_type()->name() != field_name) { |
| 284 field = NULL; | 365 field = NULL; |
| 285 } | 366 } |
| 286 | 367 |
| 287 if (field == NULL) { | 368 if (field == NULL) { |
| 288 ReportError("Message type \"" + descriptor->full_name() + | 369 if (!allow_unknown_field_) { |
| 289 "\" has no field named \"" + field_name + "\"."); | 370 ReportError("Message type \"" + descriptor->full_name() + |
| 290 return false; | 371 "\" has no field named \"" + field_name + "\"."); |
| 372 return false; |
| 373 } else { |
| 374 ReportWarning("Message type \"" + descriptor->full_name() + |
| 375 "\" has no field named \"" + field_name + "\"."); |
| 376 } |
| 377 } |
| 378 } |
| 379 |
| 380 // Skips unknown field. |
| 381 if (field == NULL) { |
| 382 GOOGLE_CHECK(allow_unknown_field_); |
| 383 // Try to guess the type of this field. |
| 384 // If this field is not a message, there should be a ":" between the |
| 385 // field name and the field value and also the field value should not |
| 386 // start with "{" or "<" which indicates the begining of a message body. |
| 387 // If there is no ":" or there is a "{" or "<" after ":", this field has |
| 388 // to be a message or the input is ill-formed. |
| 389 if (TryConsume(":") && !LookingAt("{") && !LookingAt("<")) { |
| 390 return SkipFieldValue(); |
| 391 } else { |
| 392 return SkipFieldMessage(); |
| 291 } | 393 } |
| 292 } | 394 } |
| 293 | 395 |
| 294 // Fail if the field is not repeated and it has already been specified. | 396 // Fail if the field is not repeated and it has already been specified. |
| 295 if ((singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) && | 397 if ((singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) && |
| 296 !field->is_repeated() && reflection->HasField(*message, field)) { | 398 !field->is_repeated() && reflection->HasField(*message, field)) { |
| 297 ReportError("Non-repeated field \"" + field_name + | 399 ReportError("Non-repeated field \"" + field_name + |
| 298 "\" is specified multiple times."); | 400 "\" is specified multiple times."); |
| 299 return false; | 401 return false; |
| 300 } | 402 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 322 | 424 |
| 323 // For historical reasons, fields may optionally be separated by commas or | 425 // For historical reasons, fields may optionally be separated by commas or |
| 324 // semicolons. | 426 // semicolons. |
| 325 TryConsume(";") || TryConsume(","); | 427 TryConsume(";") || TryConsume(","); |
| 326 | 428 |
| 327 if (field->options().deprecated()) { | 429 if (field->options().deprecated()) { |
| 328 ReportWarning("text format contains deprecated field \"" | 430 ReportWarning("text format contains deprecated field \"" |
| 329 + field_name + "\""); | 431 + field_name + "\""); |
| 330 } | 432 } |
| 331 | 433 |
| 434 // If a parse info tree exists, add the location for the parsed |
| 435 // field. |
| 436 if (parse_info_tree_ != NULL) { |
| 437 parse_info_tree_->RecordLocation(field, |
| 438 ParseLocation(start_line, start_column)); |
| 439 } |
| 440 |
| 441 return true; |
| 442 } |
| 443 |
| 444 // Skips the next field including the field's name and value. |
| 445 bool SkipField() { |
| 446 string field_name; |
| 447 if (TryConsume("[")) { |
| 448 // Extension name. |
| 449 DO(ConsumeIdentifier(&field_name)); |
| 450 while (TryConsume(".")) { |
| 451 string part; |
| 452 DO(ConsumeIdentifier(&part)); |
| 453 field_name += "."; |
| 454 field_name += part; |
| 455 } |
| 456 DO(Consume("]")); |
| 457 } else { |
| 458 DO(ConsumeIdentifier(&field_name)); |
| 459 } |
| 460 |
| 461 // Try to guess the type of this field. |
| 462 // If this field is not a message, there should be a ":" between the |
| 463 // field name and the field value and also the field value should not |
| 464 // start with "{" or "<" which indicates the begining of a message body. |
| 465 // If there is no ":" or there is a "{" or "<" after ":", this field has |
| 466 // to be a message or the input is ill-formed. |
| 467 if (TryConsume(":") && !LookingAt("{") && !LookingAt("<")) { |
| 468 DO(SkipFieldValue()); |
| 469 } else { |
| 470 DO(SkipFieldMessage()); |
| 471 } |
| 472 // For historical reasons, fields may optionally be separated by commas or |
| 473 // semicolons. |
| 474 TryConsume(";") || TryConsume(","); |
| 332 return true; | 475 return true; |
| 333 } | 476 } |
| 334 | 477 |
| 335 bool ConsumeFieldMessage(Message* message, | 478 bool ConsumeFieldMessage(Message* message, |
| 336 const Reflection* reflection, | 479 const Reflection* reflection, |
| 337 const FieldDescriptor* field) { | 480 const FieldDescriptor* field) { |
| 481 |
| 482 // If the parse information tree is not NULL, create a nested one |
| 483 // for the nested message. |
| 484 ParseInfoTree* parent = parse_info_tree_; |
| 485 if (parent != NULL) { |
| 486 parse_info_tree_ = parent->CreateNested(field); |
| 487 } |
| 488 |
| 338 string delimeter; | 489 string delimeter; |
| 339 if (TryConsume("<")) { | 490 if (TryConsume("<")) { |
| 340 delimeter = ">"; | 491 delimeter = ">"; |
| 341 } else { | 492 } else { |
| 342 DO(Consume("{")); | 493 DO(Consume("{")); |
| 343 delimeter = "}"; | 494 delimeter = "}"; |
| 344 } | 495 } |
| 345 | 496 |
| 346 if (field->is_repeated()) { | 497 if (field->is_repeated()) { |
| 347 DO(ConsumeMessage(reflection->AddMessage(message, field), delimeter)); | 498 DO(ConsumeMessage(reflection->AddMessage(message, field), delimeter)); |
| 348 } else { | 499 } else { |
| 349 DO(ConsumeMessage(reflection->MutableMessage(message, field), | 500 DO(ConsumeMessage(reflection->MutableMessage(message, field), |
| 350 delimeter)); | 501 delimeter)); |
| 351 } | 502 } |
| 503 |
| 504 // Reset the parse information tree. |
| 505 parse_info_tree_ = parent; |
| 506 return true; |
| 507 } |
| 508 |
| 509 // Skips the whole body of a message including the begining delimeter and |
| 510 // the ending delimeter. |
| 511 bool SkipFieldMessage() { |
| 512 string delimeter; |
| 513 if (TryConsume("<")) { |
| 514 delimeter = ">"; |
| 515 } else { |
| 516 DO(Consume("{")); |
| 517 delimeter = "}"; |
| 518 } |
| 519 while (!LookingAt(">") && !LookingAt("}")) { |
| 520 DO(SkipField()); |
| 521 } |
| 522 DO(Consume(delimeter)); |
| 352 return true; | 523 return true; |
| 353 } | 524 } |
| 354 | 525 |
| 355 bool ConsumeFieldValue(Message* message, | 526 bool ConsumeFieldValue(Message* message, |
| 356 const Reflection* reflection, | 527 const Reflection* reflection, |
| 357 const FieldDescriptor* field) { | 528 const FieldDescriptor* field) { |
| 358 | 529 |
| 359 // Define an easy to use macro for setting fields. This macro checks | 530 // Define an easy to use macro for setting fields. This macro checks |
| 360 // to see if the field is repeated (in which case we need to use the Add | 531 // to see if the field is repeated (in which case we need to use the Add |
| 361 // methods or not (in which case we need to use the Set methods). | 532 // methods or not (in which case we need to use the Set methods). |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 // We should never get here. Put here instead of a default | 643 // We should never get here. Put here instead of a default |
| 473 // so that if new types are added, we get a nice compiler warning. | 644 // so that if new types are added, we get a nice compiler warning. |
| 474 GOOGLE_LOG(FATAL) << "Reached an unintended state: CPPTYPE_MESSAGE"; | 645 GOOGLE_LOG(FATAL) << "Reached an unintended state: CPPTYPE_MESSAGE"; |
| 475 break; | 646 break; |
| 476 } | 647 } |
| 477 } | 648 } |
| 478 #undef SET_FIELD | 649 #undef SET_FIELD |
| 479 return true; | 650 return true; |
| 480 } | 651 } |
| 481 | 652 |
| 653 bool SkipFieldValue() { |
| 654 if (LookingAtType(io::Tokenizer::TYPE_STRING)) { |
| 655 while (LookingAtType(io::Tokenizer::TYPE_STRING)) { |
| 656 tokenizer_.Next(); |
| 657 } |
| 658 return true; |
| 659 } |
| 660 // Possible field values other than string: |
| 661 // 12345 => TYPE_INTEGER |
| 662 // -12345 => TYPE_SYMBOL + TYPE_INTEGER |
| 663 // 1.2345 => TYPE_FLOAT |
| 664 // -1.2345 => TYPE_SYMBOL + TYPE_FLOAT |
| 665 // inf => TYPE_IDENTIFIER |
| 666 // -inf => TYPE_SYMBOL + TYPE_IDENTIFIER |
| 667 // TYPE_INTEGER => TYPE_IDENTIFIER |
| 668 // Divides them into two group, one with TYPE_SYMBOL |
| 669 // and the other without: |
| 670 // Group one: |
| 671 // 12345 => TYPE_INTEGER |
| 672 // 1.2345 => TYPE_FLOAT |
| 673 // inf => TYPE_IDENTIFIER |
| 674 // TYPE_INTEGER => TYPE_IDENTIFIER |
| 675 // Group two: |
| 676 // -12345 => TYPE_SYMBOL + TYPE_INTEGER |
| 677 // -1.2345 => TYPE_SYMBOL + TYPE_FLOAT |
| 678 // -inf => TYPE_SYMBOL + TYPE_IDENTIFIER |
| 679 // As we can see, the field value consists of an optional '-' and one of |
| 680 // TYPE_INTEGER, TYPE_FLOAT and TYPE_IDENTIFIER. |
| 681 bool has_minus = TryConsume("-"); |
| 682 if (!LookingAtType(io::Tokenizer::TYPE_INTEGER) && |
| 683 !LookingAtType(io::Tokenizer::TYPE_FLOAT) && |
| 684 !LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { |
| 685 return false; |
| 686 } |
| 687 // Combination of '-' and TYPE_IDENTIFIER may result in an invalid field |
| 688 // value while other combinations all generate valid values. |
| 689 // We check if the value of this combination is valid here. |
| 690 // TYPE_IDENTIFIER after a '-' should be one of the float values listed |
| 691 // below: |
| 692 // inf, inff, infinity, nan |
| 693 if (has_minus && LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { |
| 694 string text = tokenizer_.current().text; |
| 695 LowerString(&text); |
| 696 if (text != "inf" && |
| 697 text != "infinity" && |
| 698 text != "nan") { |
| 699 ReportError("Invalid float number: " + text); |
| 700 return false; |
| 701 } |
| 702 } |
| 703 tokenizer_.Next(); |
| 704 return true; |
| 705 } |
| 706 |
| 482 // Returns true if the current token's text is equal to that specified. | 707 // Returns true if the current token's text is equal to that specified. |
| 483 bool LookingAt(const string& text) { | 708 bool LookingAt(const string& text) { |
| 484 return tokenizer_.current().text == text; | 709 return tokenizer_.current().text == text; |
| 485 } | 710 } |
| 486 | 711 |
| 487 // Returns true if the current token's type is equal to that specified. | 712 // Returns true if the current token's type is equal to that specified. |
| 488 bool LookingAtType(io::Tokenizer::TokenType token_type) { | 713 bool LookingAtType(io::Tokenizer::TokenType token_type) { |
| 489 return tokenizer_.current().type == token_type; | 714 return tokenizer_.current().type == token_type; |
| 490 } | 715 } |
| 491 | 716 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 *value = static_cast<double>(integer_value); | 814 *value = static_cast<double>(integer_value); |
| 590 } else if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) { | 815 } else if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) { |
| 591 // We have found a float value for the double. | 816 // We have found a float value for the double. |
| 592 *value = io::Tokenizer::ParseFloat(tokenizer_.current().text); | 817 *value = io::Tokenizer::ParseFloat(tokenizer_.current().text); |
| 593 | 818 |
| 594 // Mark the current token as consumed. | 819 // Mark the current token as consumed. |
| 595 tokenizer_.Next(); | 820 tokenizer_.Next(); |
| 596 } else if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { | 821 } else if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { |
| 597 string text = tokenizer_.current().text; | 822 string text = tokenizer_.current().text; |
| 598 LowerString(&text); | 823 LowerString(&text); |
| 599 if (text == "inf" || text == "infinity") { | 824 if (text == "inf" || |
| 825 text == "infinity") { |
| 600 *value = std::numeric_limits<double>::infinity(); | 826 *value = std::numeric_limits<double>::infinity(); |
| 601 tokenizer_.Next(); | 827 tokenizer_.Next(); |
| 602 } else if (text == "nan") { | 828 } else if (text == "nan") { |
| 603 *value = std::numeric_limits<double>::quiet_NaN(); | 829 *value = std::numeric_limits<double>::quiet_NaN(); |
| 604 tokenizer_.Next(); | 830 tokenizer_.Next(); |
| 605 } else { | 831 } else { |
| 606 ReportError("Expected double."); | 832 ReportError("Expected double."); |
| 607 return false; | 833 return false; |
| 608 } | 834 } |
| 609 } else { | 835 } else { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 parser_->ReportWarning(line, column, message); | 889 parser_->ReportWarning(line, column, message); |
| 664 } | 890 } |
| 665 | 891 |
| 666 private: | 892 private: |
| 667 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserErrorCollector); | 893 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserErrorCollector); |
| 668 TextFormat::Parser::ParserImpl* parser_; | 894 TextFormat::Parser::ParserImpl* parser_; |
| 669 }; | 895 }; |
| 670 | 896 |
| 671 io::ErrorCollector* error_collector_; | 897 io::ErrorCollector* error_collector_; |
| 672 TextFormat::Finder* finder_; | 898 TextFormat::Finder* finder_; |
| 899 ParseInfoTree* parse_info_tree_; |
| 673 ParserErrorCollector tokenizer_error_collector_; | 900 ParserErrorCollector tokenizer_error_collector_; |
| 674 io::Tokenizer tokenizer_; | 901 io::Tokenizer tokenizer_; |
| 675 const Descriptor* root_message_type_; | 902 const Descriptor* root_message_type_; |
| 676 SingularOverwritePolicy singular_overwrite_policy_; | 903 SingularOverwritePolicy singular_overwrite_policy_; |
| 904 bool allow_unknown_field_; |
| 677 bool had_errors_; | 905 bool had_errors_; |
| 678 }; | 906 }; |
| 679 | 907 |
| 680 #undef DO | 908 #undef DO |
| 681 | 909 |
| 682 // =========================================================================== | 910 // =========================================================================== |
| 683 // Internal class for writing text to the io::ZeroCopyOutputStream. Adapted | 911 // Internal class for writing text to the io::ZeroCopyOutputStream. Adapted |
| 684 // from the Printer found in //google/protobuf/io/printer.h | 912 // from the Printer found in //google/protobuf/io/printer.h |
| 685 class TextFormat::Printer::TextGenerator { | 913 class TextFormat::Printer::TextGenerator { |
| 686 public: | 914 public: |
| 687 explicit TextGenerator(io::ZeroCopyOutputStream* output, | 915 explicit TextGenerator(io::ZeroCopyOutputStream* output, |
| 688 int initial_indent_level) | 916 int initial_indent_level) |
| 689 : output_(output), | 917 : output_(output), |
| 690 buffer_(NULL), | 918 buffer_(NULL), |
| 691 buffer_size_(0), | 919 buffer_size_(0), |
| 692 at_start_of_line_(true), | 920 at_start_of_line_(true), |
| 693 failed_(false), | 921 failed_(false), |
| 694 indent_(""), | 922 indent_(""), |
| 695 initial_indent_level_(initial_indent_level) { | 923 initial_indent_level_(initial_indent_level) { |
| 696 indent_.resize(initial_indent_level_ * 2, ' '); | 924 indent_.resize(initial_indent_level_ * 2, ' '); |
| 697 } | 925 } |
| 698 | 926 |
| 699 ~TextGenerator() { | 927 ~TextGenerator() { |
| 700 // Only BackUp() if we're sure we've successfully called Next() at least | 928 // Only BackUp() if we're sure we've successfully called Next() at least |
| 701 // once. | 929 // once. |
| 702 if (buffer_size_ > 0) { | 930 if (!failed_ && buffer_size_ > 0) { |
| 703 output_->BackUp(buffer_size_); | 931 output_->BackUp(buffer_size_); |
| 704 } | 932 } |
| 705 } | 933 } |
| 706 | 934 |
| 707 // Indent text by two spaces. After calling Indent(), two spaces will be | 935 // Indent text by two spaces. After calling Indent(), two spaces will be |
| 708 // inserted at the beginning of each line of text. Indent() may be called | 936 // inserted at the beginning of each line of text. Indent() may be called |
| 709 // multiple times to produce deeper indents. | 937 // multiple times to produce deeper indents. |
| 710 void Indent() { | 938 void Indent() { |
| 711 indent_ += " "; | 939 indent_ += " "; |
| 712 } | 940 } |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 802 }; | 1030 }; |
| 803 | 1031 |
| 804 // =========================================================================== | 1032 // =========================================================================== |
| 805 | 1033 |
| 806 TextFormat::Finder::~Finder() { | 1034 TextFormat::Finder::~Finder() { |
| 807 } | 1035 } |
| 808 | 1036 |
| 809 TextFormat::Parser::Parser() | 1037 TextFormat::Parser::Parser() |
| 810 : error_collector_(NULL), | 1038 : error_collector_(NULL), |
| 811 finder_(NULL), | 1039 finder_(NULL), |
| 812 allow_partial_(false) { | 1040 parse_info_tree_(NULL), |
| 1041 allow_partial_(false), |
| 1042 allow_unknown_field_(false) { |
| 813 } | 1043 } |
| 814 | 1044 |
| 815 TextFormat::Parser::~Parser() {} | 1045 TextFormat::Parser::~Parser() {} |
| 816 | 1046 |
| 817 bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input, | 1047 bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input, |
| 818 Message* output) { | 1048 Message* output) { |
| 819 output->Clear(); | 1049 output->Clear(); |
| 820 ParserImpl parser(output->GetDescriptor(), input, error_collector_, | 1050 ParserImpl parser(output->GetDescriptor(), input, error_collector_, |
| 821 finder_, ParserImpl::FORBID_SINGULAR_OVERWRITES); | 1051 finder_, parse_info_tree_, |
| 1052 ParserImpl::FORBID_SINGULAR_OVERWRITES, |
| 1053 allow_unknown_field_); |
| 822 return MergeUsingImpl(input, output, &parser); | 1054 return MergeUsingImpl(input, output, &parser); |
| 823 } | 1055 } |
| 824 | 1056 |
| 825 bool TextFormat::Parser::ParseFromString(const string& input, | 1057 bool TextFormat::Parser::ParseFromString(const string& input, |
| 826 Message* output) { | 1058 Message* output) { |
| 827 io::ArrayInputStream input_stream(input.data(), input.size()); | 1059 io::ArrayInputStream input_stream(input.data(), input.size()); |
| 828 return Parse(&input_stream, output); | 1060 return Parse(&input_stream, output); |
| 829 } | 1061 } |
| 830 | 1062 |
| 831 bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input, | 1063 bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input, |
| 832 Message* output) { | 1064 Message* output) { |
| 833 ParserImpl parser(output->GetDescriptor(), input, error_collector_, | 1065 ParserImpl parser(output->GetDescriptor(), input, error_collector_, |
| 834 finder_, ParserImpl::ALLOW_SINGULAR_OVERWRITES); | 1066 finder_, parse_info_tree_, |
| 1067 ParserImpl::ALLOW_SINGULAR_OVERWRITES, |
| 1068 allow_unknown_field_); |
| 835 return MergeUsingImpl(input, output, &parser); | 1069 return MergeUsingImpl(input, output, &parser); |
| 836 } | 1070 } |
| 837 | 1071 |
| 838 bool TextFormat::Parser::MergeFromString(const string& input, | 1072 bool TextFormat::Parser::MergeFromString(const string& input, |
| 839 Message* output) { | 1073 Message* output) { |
| 840 io::ArrayInputStream input_stream(input.data(), input.size()); | 1074 io::ArrayInputStream input_stream(input.data(), input.size()); |
| 841 return Merge(&input_stream, output); | 1075 return Merge(&input_stream, output); |
| 842 } | 1076 } |
| 843 | 1077 |
| 844 bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* input, | 1078 bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* input, |
| 845 Message* output, | 1079 Message* output, |
| 846 ParserImpl* parser_impl) { | 1080 ParserImpl* parser_impl) { |
| 847 if (!parser_impl->Parse(output)) return false; | 1081 if (!parser_impl->Parse(output)) return false; |
| 848 if (!allow_partial_ && !output->IsInitialized()) { | 1082 if (!allow_partial_ && !output->IsInitialized()) { |
| 849 vector<string> missing_fields; | 1083 vector<string> missing_fields; |
| 850 output->FindInitializationErrors(&missing_fields); | 1084 output->FindInitializationErrors(&missing_fields); |
| 851 parser_impl->ReportError(-1, 0, "Message missing required fields: " + | 1085 parser_impl->ReportError(-1, 0, "Message missing required fields: " + |
| 852 JoinStrings(missing_fields, ", ")); | 1086 JoinStrings(missing_fields, ", ")); |
| 853 return false; | 1087 return false; |
| 854 } | 1088 } |
| 855 return true; | 1089 return true; |
| 856 } | 1090 } |
| 857 | 1091 |
| 858 bool TextFormat::Parser::ParseFieldValueFromString( | 1092 bool TextFormat::Parser::ParseFieldValueFromString( |
| 859 const string& input, | 1093 const string& input, |
| 860 const FieldDescriptor* field, | 1094 const FieldDescriptor* field, |
| 861 Message* output) { | 1095 Message* output) { |
| 862 io::ArrayInputStream input_stream(input.data(), input.size()); | 1096 io::ArrayInputStream input_stream(input.data(), input.size()); |
| 863 ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_, | 1097 ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_, |
| 864 finder_, ParserImpl::ALLOW_SINGULAR_OVERWRITES); | 1098 finder_, parse_info_tree_, |
| 1099 ParserImpl::ALLOW_SINGULAR_OVERWRITES, |
| 1100 allow_unknown_field_); |
| 865 return parser.ParseField(field, output); | 1101 return parser.ParseField(field, output); |
| 866 } | 1102 } |
| 867 | 1103 |
| 868 /* static */ bool TextFormat::Parse(io::ZeroCopyInputStream* input, | 1104 /* static */ bool TextFormat::Parse(io::ZeroCopyInputStream* input, |
| 869 Message* output) { | 1105 Message* output) { |
| 870 return Parser().Parse(input, output); | 1106 return Parser().Parse(input, output); |
| 871 } | 1107 } |
| 872 | 1108 |
| 873 /* static */ bool TextFormat::Merge(io::ZeroCopyInputStream* input, | 1109 /* static */ bool TextFormat::Merge(io::ZeroCopyInputStream* input, |
| 874 Message* output) { | 1110 Message* output) { |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1276 generator.Outdent(); | 1512 generator.Outdent(); |
| 1277 generator.Print("}\n"); | 1513 generator.Print("}\n"); |
| 1278 } | 1514 } |
| 1279 break; | 1515 break; |
| 1280 } | 1516 } |
| 1281 } | 1517 } |
| 1282 } | 1518 } |
| 1283 | 1519 |
| 1284 } // namespace protobuf | 1520 } // namespace protobuf |
| 1285 } // namespace google | 1521 } // namespace google |
| OLD | NEW |