1
1
// Protocol Buffers - Google's data interchange format
2
// Copyright 2008 Google Inc.
2
// Copyright 2008 Google Inc. All rights reserved.
3
3
// http://code.google.com/p/protobuf/
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
9
// http://www.apache.org/licenses/LICENSE-2.0
11
// Unless required by applicable law or agreed to in writing, software
12
// distributed under the License is distributed on an "AS IS" BASIS,
13
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
// See the License for the specific language governing permissions and
15
// limitations under the License.
5
// Redistribution and use in source and binary forms, with or without
6
// modification, are permitted provided that the following conditions are
9
// * Redistributions of source code must retain the above copyright
10
// notice, this list of conditions and the following disclaimer.
11
// * Redistributions in binary form must reproduce the above
12
// copyright notice, this list of conditions and the following disclaimer
13
// in the documentation and/or other materials provided with the
15
// * Neither the name of Google Inc. nor the names of its
16
// contributors may be used to endorse or promote products derived from
17
// this software without specific prior written permission.
19
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17
31
// Author: kenton@google.com (Kenton Varda)
18
32
// Based on original Protocol Buffers design by
625
bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option) {
626
UninterpretedOption::NamePart* name = uninterpreted_option->add_name();
627
string identifier; // We parse identifiers into this string.
628
if (LookingAt("(")) { // This is an extension.
630
// An extension name consists of dot-separated identifiers, and may begin
632
if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
633
DO(ConsumeIdentifier(&identifier, "Expected identifier."));
634
name->mutable_name_part()->append(identifier);
636
while (LookingAt(".")) {
638
name->mutable_name_part()->append(".");
639
DO(ConsumeIdentifier(&identifier, "Expected identifier."));
640
name->mutable_name_part()->append(identifier);
643
name->set_is_extension(true);
644
} else { // This is a regular field.
645
DO(ConsumeIdentifier(&identifier, "Expected identifier."));
646
name->mutable_name_part()->append(identifier);
647
name->set_is_extension(false);
652
// We don't interpret the option here. Instead we store it in an
653
// UninterpretedOption, to be interpreted later.
606
654
bool Parser::ParseOptionAssignment(Message* options) {
607
Message::Reflection* reflection = options->GetReflection();
608
const Descriptor* descriptor = options->GetDescriptor();
612
int line = input_->current().line;
613
int column = input_->current().column;
614
DO(ConsumeIdentifier(&name, "Expected option name."));
617
const FieldDescriptor* field = descriptor->FindFieldByName(name);
619
AddError(line, column, "Unknown option: " + name);
622
if (field->is_repeated()) {
623
AddError(line, column, "Not implemented: repeated options.");
626
if (reflection->HasField(field)) {
627
AddError(line, column, "Option \"" + name + "\" was already set.");
631
// Are we trying to assign a member of a message?
632
if (LookingAt(".")) {
633
if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
634
AddError("Option \"" + name + "\" is an atomic type, not a message.");
655
// Create an entry in the uninterpreted_option field.
656
const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()->
657
FindFieldByName("uninterpreted_option");
658
GOOGLE_CHECK(uninterpreted_option_field != NULL)
659
<< "No field named \"uninterpreted_option\" in the Options proto.";
661
UninterpretedOption* uninterpreted_option = ::google::protobuf::down_cast<UninterpretedOption*>(
662
options->GetReflection()->AddMessage(options,
663
uninterpreted_option_field));
665
// Parse dot-separated name.
666
RecordLocation(uninterpreted_option,
667
DescriptorPool::ErrorCollector::OPTION_NAME);
669
DO(ParseOptionNamePart(uninterpreted_option));
671
while (LookingAt(".")) {
637
672
DO(Consume("."));
639
// This field is a message/group. The user must identify a field within
641
return ParseOptionAssignment(reflection->MutableMessage(field));
673
DO(ParseOptionNamePart(uninterpreted_option));
644
676
DO(Consume("="));
646
// Parse the option value.
647
switch (field->cpp_type()) {
648
case FieldDescriptor::CPPTYPE_INT32: {
650
bool is_negative = TryConsume("-");
651
uint64 max_value = kint32max;
652
if (is_negative) ++max_value;
653
DO(ConsumeInteger64(max_value, &value, "Expected integer."));
654
reflection->SetInt32(field, is_negative ? -value : value);
658
case FieldDescriptor::CPPTYPE_INT64: {
660
bool is_negative = TryConsume("-");
661
uint64 max_value = kint64max;
662
if (is_negative) ++max_value;
663
DO(ConsumeInteger64(max_value, &value, "Expected integer."));
664
reflection->SetInt64(field, is_negative ? -value : value);
668
case FieldDescriptor::CPPTYPE_UINT32: {
670
DO(ConsumeInteger64(kuint32max, &value, "Expected integer."));
671
reflection->SetUInt32(field, value);
675
case FieldDescriptor::CPPTYPE_UINT64: {
677
DO(ConsumeInteger64(kuint64max, &value, "Expected integer."));
678
reflection->SetUInt64(field, value);
682
case FieldDescriptor::CPPTYPE_DOUBLE: {
684
bool is_negative = TryConsume("-");
685
DO(ConsumeNumber(&value, "Expected number."));
686
reflection->SetDouble(field, is_negative ? -value : value);
690
case FieldDescriptor::CPPTYPE_FLOAT: {
692
bool is_negative = TryConsume("-");
693
DO(ConsumeNumber(&value, "Expected number."));
694
reflection->SetFloat(field, is_negative ? -value : value);
698
case FieldDescriptor::CPPTYPE_BOOL:
699
if (TryConsume("true")) {
700
reflection->SetBool(field, true);
701
} else if (TryConsume("false")) {
702
reflection->SetBool(field, false);
678
RecordLocation(uninterpreted_option,
679
DescriptorPool::ErrorCollector::OPTION_VALUE);
681
// All values are a single token, except for negative numbers, which consist
682
// of a single '-' symbol, followed by a positive number.
683
bool is_negative = TryConsume("-");
685
switch (input_->current().type) {
686
case io::Tokenizer::TYPE_START:
687
GOOGLE_LOG(FATAL) << "Trying to read value before any tokens have been read.";
690
case io::Tokenizer::TYPE_END:
691
AddError("Unexpected end of stream while parsing option value.");
694
case io::Tokenizer::TYPE_IDENTIFIER: {
696
AddError("Invalid '-' symbol before identifier.");
700
DO(ConsumeIdentifier(&value, "Expected identifier."));
701
uninterpreted_option->set_identifier_value(value);
705
case io::Tokenizer::TYPE_INTEGER: {
708
is_negative ? static_cast<uint64>(kint64max) + 1 : kuint64max;
709
DO(ConsumeInteger64(max_value, &value, "Expected integer."));
711
uninterpreted_option->set_negative_int_value(-value);
704
AddError("Expected \"true\" or \"false\".");
709
case FieldDescriptor::CPPTYPE_ENUM: {
711
int value_line = input_->current().line;
712
int value_column = input_->current().column;
713
DO(ConsumeIdentifier(&value_name, "Expected enum value."));
714
const EnumValueDescriptor* value =
715
field->enum_type()->FindValueByName(value_name);
717
AddError(value_line, value_column,
718
"Enum type \"" + field->enum_type()->full_name() + "\" has no value "
719
"named \"" + value_name + "\".");
722
reflection->SetEnum(field, value);
726
case FieldDescriptor::CPPTYPE_STRING: {
713
uninterpreted_option->set_positive_int_value(value);
718
case io::Tokenizer::TYPE_FLOAT: {
720
DO(ConsumeNumber(&value, "Expected number."));
721
uninterpreted_option->set_double_value(is_negative ? -value : value);
725
case io::Tokenizer::TYPE_STRING: {
727
AddError("Invalid '-' symbol before string.");
728
731
DO(ConsumeString(&value, "Expected string."));
729
reflection->SetString(field, value);
732
uninterpreted_option->set_string_value(value);
733
case FieldDescriptor::CPPTYPE_MESSAGE: {
734
// TODO(kenton): Allow use of protocol buffer text format here?
735
AddError("\"" + name + "\" is a message. To set fields within it, use "
736
"syntax like \"" + name + ".foo = value\".");
736
case io::Tokenizer::TYPE_SYMBOL:
737
AddError("Expected option value.");