@@ -295,6 +295,14 @@ const Descriptor* DefaultFinderFindAnyType(const Message& message,
295295}
296296} // namespace
297297
298+ const void * TextFormat::Parser::UnsetFieldsMetadata::GetUnsetFieldAddress (
299+ const Message& message, const Reflection& reflection,
300+ const FieldDescriptor& fd) {
301+ // reflection->GetRaw() is a simple cast for any non-repeated type, so for
302+ // simplicity we just pass in char as the template argument.
303+ return &reflection.GetRaw <char >(message, &fd);
304+ }
305+
298306// ===========================================================================
299307// Internal class for parsing an ASCII representation of a Protocol Message.
300308// This class makes use of the Protocol Message compiler's tokenizer found
@@ -331,7 +339,7 @@ class TextFormat::Parser::ParserImpl {
331339 bool allow_unknown_extension, bool allow_unknown_enum,
332340 bool allow_field_number, bool allow_relaxed_whitespace,
333341 bool allow_partial, int recursion_limit,
334- bool error_on_no_op_fields )
342+ UnsetFieldsMetadata* no_op_fields )
335343 : error_collector_(error_collector),
336344 finder_ (finder),
337345 parse_info_tree_(parse_info_tree),
@@ -349,7 +357,7 @@ class TextFormat::Parser::ParserImpl {
349357 recursion_limit_(recursion_limit),
350358 had_silent_marker_(false ),
351359 had_errors_(false ),
352- error_on_no_op_fields_(error_on_no_op_fields ) {
360+ no_op_fields_(no_op_fields ) {
353361 // For backwards-compatibility with proto1, we need to allow the 'f' suffix
354362 // for floats.
355363 tokenizer_.set_allow_f_after_float (true );
@@ -834,19 +842,21 @@ class TextFormat::Parser::ParserImpl {
834842// When checking for no-op operations, We verify that both the existing value in
835843// the message and the new value are the default. If the existing field value is
836844// not the default, setting it to the default should not be treated as a no-op.
837- #define SET_FIELD (CPPTYPE, CPPTYPELCASE, VALUE ) \
838- if (field->is_repeated ()) { \
839- reflection->Add ##CPPTYPE (message, field, VALUE); \
840- } else { \
841- if (error_on_no_op_fields_ && !field->has_presence () && \
842- field->default_value_ ##CPPTYPELCASE () == \
843- reflection->Get ##CPPTYPE (*message, field) && \
844- field->default_value_ ##CPPTYPELCASE () == VALUE) { \
845- ReportError (" Input field " + field->full_name () + \
846- " did not change resulting proto." ); \
847- } else { \
848- reflection->Set ##CPPTYPE (message, field, std::move (VALUE)); \
849- } \
845+ // The pointer of this is kept in no_op_fields_ for bookkeeping.
846+ #define SET_FIELD (CPPTYPE, CPPTYPELCASE, VALUE ) \
847+ if (field->is_repeated ()) { \
848+ reflection->Add ##CPPTYPE (message, field, VALUE); \
849+ } else { \
850+ if (no_op_fields_ && !field->has_presence () && \
851+ field->default_value_ ##CPPTYPELCASE () == \
852+ reflection->Get ##CPPTYPE (*message, field) && \
853+ field->default_value_ ##CPPTYPELCASE () == VALUE) { \
854+ no_op_fields_->addresses_ .insert ( \
855+ UnsetFieldsMetadata::GetUnsetFieldAddress (*message, *reflection, \
856+ *field)); \
857+ } else { \
858+ reflection->Set ##CPPTYPE (message, field, std::move (VALUE)); \
859+ } \
850860 }
851861
852862 switch (field->cpp_type ()) {
@@ -1429,7 +1439,7 @@ class TextFormat::Parser::ParserImpl {
14291439 int recursion_limit_;
14301440 bool had_silent_marker_;
14311441 bool had_errors_;
1432- bool error_on_no_op_fields_ ;
1442+ UnsetFieldsMetadata* no_op_fields_{} ;
14331443
14341444};
14351445
@@ -1727,7 +1737,7 @@ bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input,
17271737 allow_case_insensitive_field_, allow_unknown_field_,
17281738 allow_unknown_extension_, allow_unknown_enum_,
17291739 allow_field_number_, allow_relaxed_whitespace_,
1730- allow_partial_, recursion_limit_, error_on_no_op_fields_ );
1740+ allow_partial_, recursion_limit_, no_op_fields_ );
17311741 return MergeUsingImpl (input, output, &parser);
17321742}
17331743
@@ -1752,7 +1762,7 @@ bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input,
17521762 allow_case_insensitive_field_, allow_unknown_field_,
17531763 allow_unknown_extension_, allow_unknown_enum_,
17541764 allow_field_number_, allow_relaxed_whitespace_,
1755- allow_partial_, recursion_limit_, error_on_no_op_fields_ );
1765+ allow_partial_, recursion_limit_, no_op_fields_ );
17561766 return MergeUsingImpl (input, output, &parser);
17571767}
17581768
@@ -1788,7 +1798,7 @@ bool TextFormat::Parser::ParseFieldValueFromString(absl::string_view input,
17881798 allow_case_insensitive_field_, allow_unknown_field_,
17891799 allow_unknown_extension_, allow_unknown_enum_,
17901800 allow_field_number_, allow_relaxed_whitespace_,
1791- allow_partial_, recursion_limit_, error_on_no_op_fields_ );
1801+ allow_partial_, recursion_limit_, no_op_fields_ );
17921802 return parser.ParseField (field, output);
17931803}
17941804
0 commit comments