bool ConsumeField()

in cdk/extra/protobuf/protobuf-3.19.6/src/google/protobuf/text_format.cc [412:652]


  bool ConsumeField(Message* message) {
    const Reflection* reflection = message->GetReflection();
    const Descriptor* descriptor = message->GetDescriptor();

    std::string field_name;
    bool reserved_field = false;
    const FieldDescriptor* field = nullptr;
    int start_line = tokenizer_.current().line;
    int start_column = tokenizer_.current().column;

    const FieldDescriptor* any_type_url_field;
    const FieldDescriptor* any_value_field;
    if (internal::GetAnyFieldDescriptors(*message, &any_type_url_field,
                                         &any_value_field) &&
        TryConsume("[")) {
      std::string full_type_name, prefix;
      DO(ConsumeAnyTypeUrl(&full_type_name, &prefix));
      std::string prefix_and_full_type_name =
          StrCat(prefix, full_type_name);
      DO(ConsumeBeforeWhitespace("]"));
      TryConsumeWhitespace(prefix_and_full_type_name, "Any");
      // ':' is optional between message labels and values.
      TryConsumeBeforeWhitespace(":");
      TryConsumeWhitespace(prefix_and_full_type_name, "Any");
      std::string serialized_value;
      const Descriptor* value_descriptor =
          finder_ ? finder_->FindAnyType(*message, prefix, full_type_name)
                  : DefaultFinderFindAnyType(*message, prefix, full_type_name);
      if (value_descriptor == nullptr) {
        ReportError("Could not find type \"" + prefix_and_full_type_name +
                    "\" stored in google.protobuf.Any.");
        return false;
      }
      DO(ConsumeAnyValue(value_descriptor, &serialized_value));
      if (singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) {
        // Fail if any_type_url_field has already been specified.
        if ((!any_type_url_field->is_repeated() &&
             reflection->HasField(*message, any_type_url_field)) ||
            (!any_value_field->is_repeated() &&
             reflection->HasField(*message, any_value_field))) {
          ReportError("Non-repeated Any specified multiple times.");
          return false;
        }
      }
      reflection->SetString(message, any_type_url_field,
                            prefix_and_full_type_name);
      reflection->SetString(message, any_value_field, serialized_value);
      return true;
    }
    if (TryConsume("[")) {
      // Extension.
      DO(ConsumeFullTypeName(&field_name));
      DO(ConsumeBeforeWhitespace("]"));
      TryConsumeWhitespace(message->GetTypeName(), "Extension");

      field = finder_ ? finder_->FindExtension(message, field_name)
                      : DefaultFinderFindExtension(message, field_name);

      if (field == nullptr) {
        if (!allow_unknown_field_ && !allow_unknown_extension_) {
          ReportError("Extension \"" + field_name +
                      "\" is not defined or "
                      "is not an extension of \"" +
                      descriptor->full_name() + "\".");
          return false;
        } else {
          ReportWarning("Ignoring extension \"" + field_name +
                        "\" which is not defined or is not an extension of \"" +
                        descriptor->full_name() + "\".");
        }
      }
    } else {
      DO(ConsumeIdentifierBeforeWhitespace(&field_name));
      TryConsumeWhitespace(message->GetTypeName(), "Normal");

      int32_t field_number;
      if (allow_field_number_ && safe_strto32(field_name, &field_number)) {
        if (descriptor->IsExtensionNumber(field_number)) {
          field = finder_
                      ? finder_->FindExtensionByNumber(descriptor, field_number)
                      : DefaultFinderFindExtensionByNumber(descriptor,
                                                           field_number);
        } else if (descriptor->IsReservedNumber(field_number)) {
          reserved_field = true;
        } else {
          field = descriptor->FindFieldByNumber(field_number);
        }
      } else {
        field = descriptor->FindFieldByName(field_name);
        // Group names are expected to be capitalized as they appear in the
        // .proto file, which actually matches their type names, not their
        // field names.
        if (field == nullptr) {
          std::string lower_field_name = field_name;
          LowerString(&lower_field_name);
          field = descriptor->FindFieldByName(lower_field_name);
          // If the case-insensitive match worked but the field is NOT a group,
          if (field != nullptr &&
              field->type() != FieldDescriptor::TYPE_GROUP) {
            field = nullptr;
          }
        }
        // Again, special-case group names as described above.
        if (field != nullptr && field->type() == FieldDescriptor::TYPE_GROUP &&
            field->message_type()->name() != field_name) {
          field = nullptr;
        }

        if (field == nullptr && allow_case_insensitive_field_) {
          std::string lower_field_name = field_name;
          LowerString(&lower_field_name);
          field = descriptor->FindFieldByLowercaseName(lower_field_name);
        }

        if (field == nullptr) {
          reserved_field = descriptor->IsReservedName(field_name);
        }
      }

      if (field == nullptr && !reserved_field) {
        if (!allow_unknown_field_) {
          ReportError("Message type \"" + descriptor->full_name() +
                      "\" has no field named \"" + field_name + "\".");
          return false;
        } else {
          ReportWarning("Message type \"" + descriptor->full_name() +
                        "\" has no field named \"" + field_name + "\".");
        }
      }
    }

    // Skips unknown or reserved fields.
    if (field == nullptr) {
      GOOGLE_CHECK(allow_unknown_field_ || allow_unknown_extension_ || reserved_field);

      // Try to guess the type of this field.
      // If this field is not a message, there should be a ":" between the
      // field name and the field value and also the field value should not
      // start with "{" or "<" which indicates the beginning of a message body.
      // If there is no ":" or there is a "{" or "<" after ":", this field has
      // to be a message or the input is ill-formed.
      if (TryConsumeBeforeWhitespace(":")) {
        TryConsumeWhitespace(message->GetTypeName(), "Unknown/Reserved");
        if (!LookingAt("{") && !LookingAt("<")) {
          return SkipFieldValue();
        }
      }
      return SkipFieldMessage();
    }

    if (singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) {
      // Fail if the field is not repeated and it has already been specified.
      if (!field->is_repeated() && reflection->HasField(*message, field)) {
        ReportError("Non-repeated field \"" + field_name +
                    "\" is specified multiple times.");
        return false;
      }
      // Fail if the field is a member of a oneof and another member has already
      // been specified.
      const OneofDescriptor* oneof = field->containing_oneof();
      if (oneof != nullptr && reflection->HasOneof(*message, oneof)) {
        const FieldDescriptor* other_field =
            reflection->GetOneofFieldDescriptor(*message, oneof);
        ReportError("Field \"" + field_name +
                    "\" is specified along with "
                    "field \"" +
                    other_field->name() +
                    "\", another member "
                    "of oneof \"" +
                    oneof->name() + "\".");
        return false;
      }
    }

    // Perform special handling for embedded message types.
    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
      // ':' is optional here.
      bool consumed_semicolon = TryConsumeBeforeWhitespace(":");
      TryConsumeWhitespace(message->GetTypeName(), "Normal");
      if (consumed_semicolon && field->options().weak() &&
          LookingAtType(io::Tokenizer::TYPE_STRING)) {
        // we are getting a bytes string for a weak field.
        std::string tmp;
        DO(ConsumeString(&tmp));
        MessageFactory* factory =
            finder_ ? finder_->FindExtensionFactory(field) : nullptr;
        reflection->MutableMessage(message, field, factory)
            ->ParseFromString(tmp);
        goto label_skip_parsing;
      }
    } else {
      // ':' is required here.
      DO(ConsumeBeforeWhitespace(":"));
      TryConsumeWhitespace(message->GetTypeName(), "Normal");
    }

    if (field->is_repeated() && TryConsume("[")) {
      // Short repeated format, e.g.  "foo: [1, 2, 3]".
      if (!TryConsume("]")) {
        // "foo: []" is treated as empty.
        while (true) {
          if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
            // Perform special handling for embedded message types.
            DO(ConsumeFieldMessage(message, reflection, field));
          } else {
            DO(ConsumeFieldValue(message, reflection, field));
          }
          if (TryConsume("]")) {
            break;
          }
          DO(Consume(","));
        }
      }
    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
      DO(ConsumeFieldMessage(message, reflection, field));
    } else {
      DO(ConsumeFieldValue(message, reflection, field));
    }
  label_skip_parsing:
    // For historical reasons, fields may optionally be separated by commas or
    // semicolons.
    TryConsume(";") || TryConsume(",");

    if (field->options().deprecated()) {
      ReportWarning("text format contains deprecated field \"" + field_name +
                    "\"");
    }

    // If a parse info tree exists, add the location for the parsed
    // field.
    if (parse_info_tree_ != nullptr) {
      int end_line = tokenizer_.previous().line;
      int end_column = tokenizer_.previous().end_column;

      RecordLocation(parse_info_tree_, field,
                     ParseLocationRange(ParseLocation(start_line, start_column),
                                        ParseLocation(end_line, end_column)));
    }

    return true;
  }