19#include "absl/strings/str_cat.h"
20#include "absl/strings/str_split.h"
21#include "google/protobuf/io/tokenizer.h"
22#include "google/protobuf/text_format.h"
27class TextFormatErrorCollector :
public google::protobuf::io::ErrorCollector {
29 struct CollectedError {
36 TextFormatErrorCollector() =
default;
37 ~TextFormatErrorCollector()
override =
default;
39 void RecordError(
const int line,
const int column,
40 absl::string_view
message)
override {
41 collected_errors_.push_back(
45 void RecordWarning(
const int line,
const int column,
46 absl::string_view
message)
override {
47 collected_errors_.push_back(
56 std::string RenderErrorMessage(
const absl::string_view
value) {
58 std::vector<std::string> value_lines = absl::StrSplit(
value,
'\n');
59 for (
const auto& error : collected_errors_) {
61 absl::StrAppend(&
message,
"warning: ");
63 absl::StrAppend(&
message, error.message,
"\n");
64 if (error.line >= 0 && error.line < value_lines.size()) {
65 const std::string& error_line = value_lines[error.line];
66 if (error.column >= 0 && error.column < error_line.size()) {
68 absl::StrAppend(&
message, error_line,
"\n");
69 absl::StrAppend(&
message, std::string(error.column,
' '),
"^\n");
77 std::vector<CollectedError> collected_errors_;
83 google::protobuf::Message*
const message_out,
84 std::string*
const error_out) {
85 TextFormatErrorCollector errors;
86 google::protobuf::TextFormat::Parser parser;
87 parser.RecordErrorsTo(&errors);
88 const bool success = parser.ParseFromString(std::string(text), message_out);
89 *error_out = errors.RenderErrorMessage(text);
In SWIG mode, we don't want anything besides these top-level includes.
bool ParseTextProtoForFlag(const absl::string_view text, google::protobuf::Message *const message_out, std::string *const error_out)