1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 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 14 // distribution. 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. 18 // 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. 30 31 // Author: jschorr@google.com (Joseph Schorr) 32 // Based on original Protocol Buffers design by 33 // Sanjay Ghemawat, Jeff Dean, and others. 34 // 35 // This file defines static methods and classes for comparing Protocol 36 // Messages. 37 // 38 // Aug. 2008: Added Unknown Fields Comparison for messages. 39 // Aug. 2009: Added different options to compare repeated fields. 40 // Apr. 2010: Moved field comparison to FieldComparator. 41 42 #ifndef GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__ 43 #define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__ 44 45 #include <functional> 46 #include <map> 47 #include <set> 48 #include <string> 49 #include <vector> 50 51 #include <google/protobuf/descriptor.h> // FieldDescriptor 52 #include <google/protobuf/message.h> // Message 53 #include <google/protobuf/unknown_field_set.h> 54 #include <google/protobuf/util/field_comparator.h> 55 56 // Always include as last one, otherwise it can break compilation 57 #include <google/protobuf/port_def.inc> 58 59 namespace google { 60 namespace protobuf { 61 62 class DynamicMessageFactory; 63 class FieldDescriptor; 64 65 namespace io { 66 class ZeroCopyOutputStream; 67 class Printer; 68 } // namespace io 69 70 namespace util { 71 72 class DefaultFieldComparator; 73 class FieldContext; // declared below MessageDifferencer 74 75 // Defines a collection of field descriptors. 76 // In case of internal google codebase we are using absl::FixedArray instead 77 // of vector. It significantly speeds up proto comparison (by ~30%) by 78 // reducing the number of malloc/free operations 79 typedef std::vector<const FieldDescriptor*> FieldDescriptorArray; 80 81 // A basic differencer that can be used to determine 82 // the differences between two specified Protocol Messages. If any differences 83 // are found, the Compare method will return false, and any differencer reporter 84 // specified via ReportDifferencesTo will have its reporting methods called (see 85 // below for implementation of the report). Based off of the original 86 // ProtocolDifferencer implementation in //net/proto/protocol-differencer.h 87 // (Thanks Todd!). 88 // 89 // MessageDifferencer REQUIRES that compared messages be the same type, defined 90 // as messages that share the same descriptor. If not, the behavior of this 91 // class is undefined. 92 // 93 // People disagree on what MessageDifferencer should do when asked to compare 94 // messages with different descriptors. Some people think it should always 95 // return false. Others expect it to try to look for similar fields and 96 // compare them anyway -- especially if the descriptors happen to be identical. 97 // If we chose either of these behaviors, some set of people would find it 98 // surprising, and could end up writing code expecting the other behavior 99 // without realizing their error. Therefore, we forbid that usage. 100 // 101 // This class is implemented based on the proto2 reflection. The performance 102 // should be good enough for normal usages. However, for places where the 103 // performance is extremely sensitive, there are several alternatives: 104 // - Comparing serialized string 105 // Downside: false negatives (there are messages that are the same but their 106 // serialized strings are different). 107 // - Equals code generator by compiler plugin (net/proto2/contrib/equals_plugin) 108 // Downside: more generated code; maintenance overhead for the additional rule 109 // (must be in sync with the original proto_library). 110 // 111 // Note on handling of google.protobuf.Any: MessageDifferencer automatically 112 // unpacks Any::value into a Message and compares its individual fields. 113 // Messages encoded in a repeated Any cannot be compared using TreatAsMap. 114 // 115 // 116 // Note on thread-safety: MessageDifferencer is *not* thread-safe. You need to 117 // guard it with a lock to use the same MessageDifferencer instance from 118 // multiple threads. Note that it's fine to call static comparison methods 119 // (like MessageDifferencer::Equals) concurrently. 120 class PROTOBUF_EXPORT MessageDifferencer { 121 public: 122 // Determines whether the supplied messages are equal. Equality is defined as 123 // all fields within the two messages being set to the same value. Primitive 124 // fields and strings are compared by value while embedded messages/groups 125 // are compared as if via a recursive call. Use Compare() with IgnoreField() 126 // if some fields should be ignored in the comparison. Use Compare() with 127 // TreatAsSet() if there are repeated fields where ordering does not matter. 128 // 129 // This method REQUIRES that the two messages have the same 130 // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). 131 static bool Equals(const Message& message1, const Message& message2); 132 133 // Determines whether the supplied messages are equivalent. Equivalency is 134 // defined as all fields within the two messages having the same value. This 135 // differs from the Equals method above in that fields with default values 136 // are considered set to said value automatically. For details on how default 137 // values are defined for each field type, see: 138 // https://developers.google.com/protocol-buffers/docs/proto?csw=1#optional. 139 // Also, Equivalent() ignores unknown fields. Use IgnoreField() and Compare() 140 // if some fields should be ignored in the comparison. 141 // 142 // This method REQUIRES that the two messages have the same 143 // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). 144 static bool Equivalent(const Message& message1, const Message& message2); 145 146 // Determines whether the supplied messages are approximately equal. 147 // Approximate equality is defined as all fields within the two messages 148 // being approximately equal. Primitive (non-float) fields and strings are 149 // compared by value, floats are compared using MathUtil::AlmostEquals() and 150 // embedded messages/groups are compared as if via a recursive call. Use 151 // IgnoreField() and Compare() if some fields should be ignored in the 152 // comparison. 153 // 154 // This method REQUIRES that the two messages have the same 155 // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). 156 static bool ApproximatelyEquals(const Message& message1, 157 const Message& message2); 158 159 // Determines whether the supplied messages are approximately equivalent. 160 // Approximate equivalency is defined as all fields within the two messages 161 // being approximately equivalent. As in 162 // MessageDifferencer::ApproximatelyEquals, primitive (non-float) fields and 163 // strings are compared by value, floats are compared using 164 // MathUtil::AlmostEquals() and embedded messages/groups are compared as if 165 // via a recursive call. However, fields with default values are considered 166 // set to said value, as per MessageDiffencer::Equivalent. Use IgnoreField() 167 // and Compare() if some fields should be ignored in the comparison. 168 // 169 // This method REQUIRES that the two messages have the same 170 // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). 171 static bool ApproximatelyEquivalent(const Message& message1, 172 const Message& message2); 173 174 // Identifies an individual field in a message instance. Used for field_path, 175 // below. 176 struct SpecificField { 177 // For known fields, "field" is filled in and "unknown_field_number" is -1. 178 // For unknown fields, "field" is NULL, "unknown_field_number" is the field 179 // number, and "unknown_field_type" is its type. 180 const FieldDescriptor* field; 181 int unknown_field_number; 182 UnknownField::Type unknown_field_type; 183 184 // If this a repeated field, "index" is the index within it. For unknown 185 // fields, this is the index of the field among all unknown fields of the 186 // same field number and type. 187 int index; 188 189 // If "field" is a repeated field which is being treated as a map or 190 // a set (see TreatAsMap() and TreatAsSet(), below), new_index indicates 191 // the index the position to which the element has moved. If the element 192 // has not moved, "new_index" will have the same value as "index". 193 int new_index; 194 195 // For unknown fields, these are the pointers to the UnknownFieldSet 196 // containing the unknown fields. In certain cases (e.g. proto1's 197 // MessageSet, or nested groups of unknown fields), these may differ from 198 // the messages' internal UnknownFieldSets. 199 const UnknownFieldSet* unknown_field_set1; 200 const UnknownFieldSet* unknown_field_set2; 201 202 // For unknown fields, these are the index of the field within the 203 // UnknownFieldSets. One or the other will be -1 when 204 // reporting an addition or deletion. 205 int unknown_field_index1; 206 int unknown_field_index2; 207 SpecificFieldSpecificField208 SpecificField() 209 : field(NULL), 210 unknown_field_number(-1), 211 index(-1), 212 new_index(-1), 213 unknown_field_set1(NULL), 214 unknown_field_set2(NULL), 215 unknown_field_index1(-1), 216 unknown_field_index2(-1) {} 217 }; 218 219 // Abstract base class from which all MessageDifferencer 220 // reporters derive. The five Report* methods below will be called when 221 // a field has been added, deleted, modified, moved, or matched. The third 222 // argument is a vector of FieldDescriptor pointers which describes the chain 223 // of fields that was taken to find the current field. For example, for a 224 // field found in an embedded message, the vector will contain two 225 // FieldDescriptors. The first will be the field of the embedded message 226 // itself and the second will be the actual field in the embedded message 227 // that was added/deleted/modified. 228 class PROTOBUF_EXPORT Reporter { 229 public: 230 Reporter(); 231 virtual ~Reporter(); 232 233 // Reports that a field has been added into Message2. 234 virtual void ReportAdded(const Message& message1, const Message& message2, 235 const std::vector<SpecificField>& field_path) = 0; 236 237 // Reports that a field has been deleted from Message1. 238 virtual void ReportDeleted( 239 const Message& message1, const Message& message2, 240 const std::vector<SpecificField>& field_path) = 0; 241 242 // Reports that the value of a field has been modified. 243 virtual void ReportModified( 244 const Message& message1, const Message& message2, 245 const std::vector<SpecificField>& field_path) = 0; 246 247 // Reports that a repeated field has been moved to another location. This 248 // only applies when using TreatAsSet or TreatAsMap() -- see below. Also 249 // note that for any given field, ReportModified and ReportMoved are 250 // mutually exclusive. If a field has been both moved and modified, then 251 // only ReportModified will be called. ReportMoved(const Message &,const Message &,const std::vector<SpecificField> &)252 virtual void ReportMoved( 253 const Message& /* message1 */, const Message& /* message2 */, 254 const std::vector<SpecificField>& /* field_path */) {} 255 256 // Reports that two fields match. Useful for doing side-by-side diffs. 257 // This function is mutually exclusive with ReportModified and ReportMoved. 258 // Note that you must call set_report_matches(true) before calling Compare 259 // to make use of this function. ReportMatched(const Message &,const Message &,const std::vector<SpecificField> &)260 virtual void ReportMatched( 261 const Message& /* message1 */, const Message& /* message2 */, 262 const std::vector<SpecificField>& /* field_path */) {} 263 264 // Reports that two fields would have been compared, but the 265 // comparison has been skipped because the field was marked as 266 // 'ignored' using IgnoreField(). This function is mutually 267 // exclusive with all the other Report() functions. 268 // 269 // The contract of ReportIgnored is slightly different than the 270 // other Report() functions, in that |field_path.back().index| is 271 // always equal to -1, even if the last field is repeated. This is 272 // because while the other Report() functions indicate where in a 273 // repeated field the action (Addition, Deletion, etc...) 274 // happened, when a repeated field is 'ignored', the differencer 275 // simply calls ReportIgnored on the repeated field as a whole and 276 // moves on without looking at its individual elements. 277 // 278 // Furthermore, ReportIgnored() does not indicate whether the 279 // fields were in fact equal or not, as Compare() does not inspect 280 // these fields at all. It is up to the Reporter to decide whether 281 // the fields are equal or not (perhaps with a second call to 282 // Compare()), if it cares. ReportIgnored(const Message &,const Message &,const std::vector<SpecificField> &)283 virtual void ReportIgnored( 284 const Message& /* message1 */, const Message& /* message2 */, 285 const std::vector<SpecificField>& /* field_path */) {} 286 287 // Report that an unknown field is ignored. (see comment above). 288 // Note this is a different function since the last SpecificField in field 289 // path has a null field. This could break existing Reporter. ReportUnknownFieldIgnored(const Message &,const Message &,const std::vector<SpecificField> &)290 virtual void ReportUnknownFieldIgnored( 291 const Message& /* message1 */, const Message& /* message2 */, 292 const std::vector<SpecificField>& /* field_path */) {} 293 294 private: 295 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reporter); 296 }; 297 298 // MapKeyComparator is used to determine if two elements have the same key 299 // when comparing elements of a repeated field as a map. 300 class PROTOBUF_EXPORT MapKeyComparator { 301 public: 302 MapKeyComparator(); 303 virtual ~MapKeyComparator(); 304 IsMatch(const Message &,const Message &,const std::vector<SpecificField> &)305 virtual bool IsMatch( 306 const Message& /* message1 */, const Message& /* message2 */, 307 const std::vector<SpecificField>& /* parent_fields */) const { 308 GOOGLE_CHECK(false) << "IsMatch() is not implemented."; 309 return false; 310 } 311 312 private: 313 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapKeyComparator); 314 }; 315 316 // Abstract base class from which all IgnoreCriteria derive. 317 // By adding IgnoreCriteria more complex ignore logic can be implemented. 318 // IgnoreCriteria are registed with AddIgnoreCriteria. For each compared 319 // field IsIgnored is called on each added IgnoreCriteria until one returns 320 // true or all return false. 321 // IsIgnored is called for fields where at least one side has a value. 322 class PROTOBUF_EXPORT IgnoreCriteria { 323 public: 324 IgnoreCriteria(); 325 virtual ~IgnoreCriteria(); 326 327 // Returns true if the field should be ignored. 328 virtual bool IsIgnored( 329 const Message& /* message1 */, const Message& /* message2 */, 330 const FieldDescriptor* /* field */, 331 const std::vector<SpecificField>& /* parent_fields */) = 0; 332 333 // Returns true if the unknown field should be ignored. 334 // Note: This will be called for unknown fields as well in which case 335 // field.field will be null. IsUnknownFieldIgnored(const Message &,const Message &,const SpecificField &,const std::vector<SpecificField> &)336 virtual bool IsUnknownFieldIgnored( 337 const Message& /* message1 */, const Message& /* message2 */, 338 const SpecificField& /* field */, 339 const std::vector<SpecificField>& /* parent_fields */) { 340 return false; 341 } 342 }; 343 344 // To add a Reporter, construct default here, then use ReportDifferencesTo or 345 // ReportDifferencesToString. 346 explicit MessageDifferencer(); 347 348 ~MessageDifferencer(); 349 350 enum MessageFieldComparison { 351 EQUAL, // Fields must be present in both messages 352 // for the messages to be considered the same. 353 EQUIVALENT, // Fields with default values are considered set 354 // for comparison purposes even if not explicitly 355 // set in the messages themselves. Unknown fields 356 // are ignored. 357 }; 358 359 enum Scope { 360 FULL, // All fields of both messages are considered in the comparison. 361 PARTIAL // Only fields present in the first message are considered; fields 362 // set only in the second message will be skipped during 363 // comparison. 364 }; 365 366 // DEPRECATED. Use FieldComparator::FloatComparison instead. 367 enum FloatComparison { 368 EXACT, // Floats and doubles are compared exactly. 369 APPROXIMATE // Floats and doubles are compared using the 370 // MathUtil::AlmostEquals method. 371 }; 372 373 enum RepeatedFieldComparison { 374 AS_LIST, // Repeated fields are compared in order. Differing values at 375 // the same index are reported using ReportModified(). If the 376 // repeated fields have different numbers of elements, the 377 // unpaired elements are reported using ReportAdded() or 378 // ReportDeleted(). 379 AS_SET, // Treat all the repeated fields as sets. 380 // See TreatAsSet(), as below. 381 AS_SMART_LIST, // Similar to AS_SET, but preserve the order and find the 382 // longest matching sequence from the first matching 383 // element. To use an optimal solution, call 384 // SetMatchIndicesForSmartListCallback() to pass it in. 385 AS_SMART_SET, // Similar to AS_SET, but match elements with fewest diffs. 386 }; 387 388 // The elements of the given repeated field will be treated as a set for 389 // diffing purposes, so different orderings of the same elements will be 390 // considered equal. Elements which are present on both sides of the 391 // comparison but which have changed position will be reported with 392 // ReportMoved(). Elements which only exist on one side or the other are 393 // reported with ReportAdded() and ReportDeleted() regardless of their 394 // positions. ReportModified() is never used for this repeated field. If 395 // the only differences between the compared messages is that some fields 396 // have been moved, then the comparison returns true. 397 // 398 // Note that despite the name of this method, this is really 399 // comparison as multisets: if one side of the comparison has a duplicate 400 // in the repeated field but the other side doesn't, this will count as 401 // a mismatch. 402 // 403 // If the scope of comparison is set to PARTIAL, then in addition to what's 404 // above, extra values added to repeated fields of the second message will 405 // not cause the comparison to fail. 406 // 407 // Note that set comparison is currently O(k * n^2) (where n is the total 408 // number of elements, and k is the average size of each element). In theory 409 // it could be made O(n * k) with a more complex hashing implementation. Feel 410 // free to contribute one if the current implementation is too slow for you. 411 // If partial matching is also enabled, the time complexity will be O(k * n^2 412 // + n^3) in which n^3 is the time complexity of the maximum matching 413 // algorithm. 414 // 415 // REQUIRES: field->is_repeated() and field not registered with TreatAsList 416 void TreatAsSet(const FieldDescriptor* field); 417 void TreatAsSmartSet(const FieldDescriptor* field); 418 419 // The elements of the given repeated field will be treated as a list for 420 // diffing purposes, so different orderings of the same elements will NOT be 421 // considered equal. 422 // 423 // REQUIRED: field->is_repeated() and field not registered with TreatAsSet 424 void TreatAsList(const FieldDescriptor* field); 425 // Note that the complexity is similar to treating as SET. 426 void TreatAsSmartList(const FieldDescriptor* field); 427 428 // The elements of the given repeated field will be treated as a map for 429 // diffing purposes, with |key| being the map key. Thus, elements with the 430 // same key will be compared even if they do not appear at the same index. 431 // Differences are reported similarly to TreatAsSet(), except that 432 // ReportModified() is used to report elements with the same key but 433 // different values. Note that if an element is both moved and modified, 434 // only ReportModified() will be called. As with TreatAsSet, if the only 435 // differences between the compared messages is that some fields have been 436 // moved, then the comparison returns true. See TreatAsSet for notes on 437 // performance. 438 // 439 // REQUIRES: field->is_repeated() 440 // REQUIRES: field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE 441 // REQUIRES: key->containing_type() == field->message_type() 442 void TreatAsMap(const FieldDescriptor* field, const FieldDescriptor* key); 443 // Same as TreatAsMap except that this method will use multiple fields as 444 // the key in comparison. All specified fields in 'key_fields' should be 445 // present in the compared elements. Two elements will be treated as having 446 // the same key iff they have the same value for every specified field. There 447 // are two steps in the comparison process. The first one is key matching. 448 // Every element from one message will be compared to every element from 449 // the other message. Only fields in 'key_fields' are compared in this step 450 // to decide if two elements have the same key. The second step is value 451 // comparison. Those pairs of elements with the same key (with equal value 452 // for every field in 'key_fields') will be compared in this step. 453 // Time complexity of the first step is O(s * m * n ^ 2) where s is the 454 // average size of the fields specified in 'key_fields', m is the number of 455 // fields in 'key_fields' and n is the number of elements. If partial 456 // matching is enabled, an extra O(n^3) will be incured by the maximum 457 // matching algorithm. The second step is O(k * n) where k is the average 458 // size of each element. 459 void TreatAsMapWithMultipleFieldsAsKey( 460 const FieldDescriptor* field, 461 const std::vector<const FieldDescriptor*>& key_fields); 462 // Same as TreatAsMapWithMultipleFieldsAsKey, except that each of the field 463 // do not necessarily need to be a direct subfield. Each element in 464 // key_field_paths indicate a path from the message being compared, listing 465 // successive subfield to reach the key field. 466 // 467 // REQUIRES: 468 // for key_field_path in key_field_paths: 469 // key_field_path[0]->containing_type() == field->message_type() 470 // for i in [0, key_field_path.size() - 1): 471 // key_field_path[i+1]->containing_type() == 472 // key_field_path[i]->message_type() 473 // key_field_path[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE 474 // !key_field_path[i]->is_repeated() 475 void TreatAsMapWithMultipleFieldPathsAsKey( 476 const FieldDescriptor* field, 477 const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths); 478 479 // Uses a custom MapKeyComparator to determine if two elements have the same 480 // key when comparing a repeated field as a map. 481 // The caller is responsible to delete the key_comparator. 482 // This method varies from TreatAsMapWithMultipleFieldsAsKey only in the 483 // first key matching step. Rather than comparing some specified fields, it 484 // will invoke the IsMatch method of the given 'key_comparator' to decide if 485 // two elements have the same key. 486 void TreatAsMapUsingKeyComparator(const FieldDescriptor* field, 487 const MapKeyComparator* key_comparator); 488 489 // Initiates and returns a new instance of MultipleFieldsMapKeyComparator. 490 MapKeyComparator* CreateMultipleFieldsMapKeyComparator( 491 const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths); 492 493 // Add a custom ignore criteria that is evaluated in addition to the 494 // ignored fields added with IgnoreField. 495 // Takes ownership of ignore_criteria. 496 void AddIgnoreCriteria(IgnoreCriteria* ignore_criteria); 497 498 // Indicates that any field with the given descriptor should be 499 // ignored for the purposes of comparing two messages. This applies 500 // to fields nested in the message structure as well as top level 501 // ones. When the MessageDifferencer encounters an ignored field, 502 // ReportIgnored is called on the reporter, if one is specified. 503 // 504 // The only place where the field's 'ignored' status is not applied is when 505 // it is being used as a key in a field passed to TreatAsMap or is one of 506 // the fields passed to TreatAsMapWithMultipleFieldsAsKey. 507 // In this case it is compared in key matching but after that it's ignored 508 // in value comparison. 509 void IgnoreField(const FieldDescriptor* field); 510 511 // Sets the field comparator used to determine differences between protocol 512 // buffer fields. By default it's set to a DefaultFieldComparator instance. 513 // MessageDifferencer doesn't take ownership over the passed object. 514 // Note that this method must be called before Compare for the comparator to 515 // be used. 516 void set_field_comparator(FieldComparator* comparator); 517 518 // DEPRECATED. Pass a DefaultFieldComparator instance instead. 519 // Sets the fraction and margin for the float comparison of a given field. 520 // Uses MathUtil::WithinFractionOrMargin to compare the values. 521 // NOTE: this method does nothing if differencer's field comparator has been 522 // set to a custom object. 523 // 524 // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or 525 // field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT 526 // REQUIRES: float_comparison_ == APPROXIMATE 527 void SetFractionAndMargin(const FieldDescriptor* field, double fraction, 528 double margin); 529 530 // Sets the type of comparison (as defined in the MessageFieldComparison 531 // enumeration above) that is used by this differencer when determining how 532 // to compare fields in messages. 533 void set_message_field_comparison(MessageFieldComparison comparison); 534 535 // Tells the differencer whether or not to report matches. This method must 536 // be called before Compare. The default for a new differencer is false. set_report_matches(bool report_matches)537 void set_report_matches(bool report_matches) { 538 report_matches_ = report_matches; 539 } 540 541 // Tells the differencer whether or not to report moves (in a set or map 542 // repeated field). This method must be called before Compare. The default for 543 // a new differencer is true. set_report_moves(bool report_moves)544 void set_report_moves(bool report_moves) { report_moves_ = report_moves; } 545 546 // Tells the differencer whether or not to report ignored values. This method 547 // must be called before Compare. The default for a new differencer is true. set_report_ignores(bool report_ignores)548 void set_report_ignores(bool report_ignores) { 549 report_ignores_ = report_ignores; 550 } 551 552 // Sets the scope of the comparison (as defined in the Scope enumeration 553 // above) that is used by this differencer when determining which fields to 554 // compare between the messages. 555 void set_scope(Scope scope); 556 557 // Returns the current scope used by this differencer. 558 Scope scope(); 559 560 // DEPRECATED. Pass a DefaultFieldComparator instance instead. 561 // Sets the type of comparison (as defined in the FloatComparison enumeration 562 // above) that is used by this differencer when comparing float (and double) 563 // fields in messages. 564 // NOTE: this method does nothing if differencer's field comparator has been 565 // set to a custom object. 566 void set_float_comparison(FloatComparison comparison); 567 568 // Sets the type of comparison for repeated field (as defined in the 569 // RepeatedFieldComparison enumeration above) that is used by this 570 // differencer when compare repeated fields in messages. 571 void set_repeated_field_comparison(RepeatedFieldComparison comparison); 572 573 // Compares the two specified messages, returning true if they are the same, 574 // false otherwise. If this method returns false, any changes between the 575 // two messages will be reported if a Reporter was specified via 576 // ReportDifferencesTo (see also ReportDifferencesToString). 577 // 578 // This method REQUIRES that the two messages have the same 579 // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). 580 bool Compare(const Message& message1, const Message& message2); 581 582 // Same as above, except comparing only the list of fields specified by the 583 // two vectors of FieldDescriptors. 584 bool CompareWithFields( 585 const Message& message1, const Message& message2, 586 const std::vector<const FieldDescriptor*>& message1_fields, 587 const std::vector<const FieldDescriptor*>& message2_fields); 588 589 // Automatically creates a reporter that will output the differences 590 // found (if any) to the specified output string pointer. Note that this 591 // method must be called before Compare. 592 void ReportDifferencesToString(std::string* output); 593 594 // Tells the MessageDifferencer to report differences via the specified 595 // reporter. Note that this method must be called before Compare for 596 // the reporter to be used. It is the responsibility of the caller to delete 597 // this object. 598 // If the provided pointer equals NULL, the MessageDifferencer stops reporting 599 // differences to any previously set reporters or output strings. 600 void ReportDifferencesTo(Reporter* reporter); 601 602 // An implementation of the MessageDifferencer Reporter that outputs 603 // any differences found in human-readable form to the supplied 604 // ZeroCopyOutputStream or Printer. If a printer is used, the delimiter 605 // *must* be '$'. 606 // 607 // WARNING: this reporter does not necessarily flush its output until it is 608 // destroyed. As a result, it is not safe to assume the output is valid or 609 // complete until after you destroy the reporter. For example, if you use a 610 // StreamReporter to write to a StringOutputStream, the target string may 611 // contain uninitialized data until the reporter is destroyed. 612 class PROTOBUF_EXPORT StreamReporter : public Reporter { 613 public: 614 explicit StreamReporter(io::ZeroCopyOutputStream* output); 615 explicit StreamReporter(io::Printer* printer); // delimiter '$' 616 ~StreamReporter() override; 617 618 // When set to true, the stream reporter will also output aggregates nodes 619 // (i.e. messages and groups) whose subfields have been modified. When 620 // false, will only report the individual subfields. Defaults to false. set_report_modified_aggregates(bool report)621 void set_report_modified_aggregates(bool report) { 622 report_modified_aggregates_ = report; 623 } 624 625 // The following are implementations of the methods described above. 626 627 void ReportAdded(const Message& message1, const Message& message2, 628 const std::vector<SpecificField>& field_path) override; 629 630 void ReportDeleted(const Message& message1, const Message& message2, 631 const std::vector<SpecificField>& field_path) override; 632 633 void ReportModified(const Message& message1, const Message& message2, 634 const std::vector<SpecificField>& field_path) override; 635 636 void ReportMoved(const Message& message1, const Message& message2, 637 const std::vector<SpecificField>& field_path) override; 638 639 void ReportMatched(const Message& message1, const Message& message2, 640 const std::vector<SpecificField>& field_path) override; 641 642 void ReportIgnored(const Message& message1, const Message& message2, 643 const std::vector<SpecificField>& field_path) override; 644 645 void ReportUnknownFieldIgnored( 646 const Message& message1, const Message& message2, 647 const std::vector<SpecificField>& field_path) override; 648 649 protected: 650 // Prints the specified path of fields to the buffer. message is used to 651 // print map keys. 652 virtual void PrintPath(const std::vector<SpecificField>& field_path, 653 bool left_side, const Message& message); 654 655 // Prints the specified path of fields to the buffer. 656 virtual void PrintPath(const std::vector<SpecificField>& field_path, 657 bool left_side); 658 659 // Prints the value of fields to the buffer. left_side is true if the 660 // given message is from the left side of the comparison, false if it 661 // was the right. This is relevant only to decide whether to follow 662 // unknown_field_index1 or unknown_field_index2 when an unknown field 663 // is encountered in field_path. 664 virtual void PrintValue(const Message& message, 665 const std::vector<SpecificField>& field_path, 666 bool left_side); 667 668 // Prints the specified path of unknown fields to the buffer. 669 virtual void PrintUnknownFieldValue(const UnknownField* unknown_field); 670 671 // Just print a string 672 void Print(const std::string& str); 673 674 private: 675 io::Printer* printer_; 676 bool delete_printer_; 677 bool report_modified_aggregates_; 678 679 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StreamReporter); 680 }; 681 682 private: 683 friend class DefaultFieldComparator; 684 685 // A MapKeyComparator to be used in TreatAsMapUsingKeyComparator. 686 // Implementation of this class needs to do field value comparison which 687 // relies on some private methods of MessageDifferencer. That's why this 688 // class is declared as a nested class of MessageDifferencer. 689 class MultipleFieldsMapKeyComparator; 690 691 // A MapKeyComparator for use with map_entries. 692 class PROTOBUF_EXPORT MapEntryKeyComparator : public MapKeyComparator { 693 public: 694 explicit MapEntryKeyComparator(MessageDifferencer* message_differencer); 695 bool IsMatch( 696 const Message& message1, const Message& message2, 697 const std::vector<SpecificField>& parent_fields) const override; 698 699 private: 700 MessageDifferencer* message_differencer_; 701 }; 702 703 // Returns true if field1's number() is less than field2's. 704 static bool FieldBefore(const FieldDescriptor* field1, 705 const FieldDescriptor* field2); 706 707 // Retrieve all the set fields, including extensions. 708 FieldDescriptorArray RetrieveFields(const Message& message, 709 bool base_message); 710 711 // Combine the two lists of fields into the combined_fields output vector. 712 // All fields present in both lists will always be included in the combined 713 // list. Fields only present in one of the lists will only appear in the 714 // combined list if the corresponding fields_scope option is set to FULL. 715 FieldDescriptorArray CombineFields(const FieldDescriptorArray& fields1, 716 Scope fields1_scope, 717 const FieldDescriptorArray& fields2, 718 Scope fields2_scope); 719 720 // Internal version of the Compare method which performs the actual 721 // comparison. The parent_fields vector is a vector containing field 722 // descriptors of all fields accessed to get to this comparison operation 723 // (i.e. if the current message is an embedded message, the parent_fields 724 // vector will contain the field that has this embedded message). 725 bool Compare(const Message& message1, const Message& message2, 726 std::vector<SpecificField>* parent_fields); 727 728 // Compares all the unknown fields in two messages. 729 bool CompareUnknownFields(const Message& message1, const Message& message2, 730 const UnknownFieldSet&, const UnknownFieldSet&, 731 std::vector<SpecificField>* parent_fields); 732 733 // Compares the specified messages for the requested field lists. The field 734 // lists are modified depending on comparison settings, and then passed to 735 // CompareWithFieldsInternal. 736 bool CompareRequestedFieldsUsingSettings( 737 const Message& message1, const Message& message2, 738 const FieldDescriptorArray& message1_fields, 739 const FieldDescriptorArray& message2_fields, 740 std::vector<SpecificField>* parent_fields); 741 742 // Compares the specified messages with the specified field lists. 743 bool CompareWithFieldsInternal(const Message& message1, 744 const Message& message2, 745 const FieldDescriptorArray& message1_fields, 746 const FieldDescriptorArray& message2_fields, 747 std::vector<SpecificField>* parent_fields); 748 749 // Compares the repeated fields, and report the error. 750 bool CompareRepeatedField(const Message& message1, const Message& message2, 751 const FieldDescriptor* field, 752 std::vector<SpecificField>* parent_fields); 753 754 // Shorthand for CompareFieldValueUsingParentFields with NULL parent_fields. 755 bool CompareFieldValue(const Message& message1, const Message& message2, 756 const FieldDescriptor* field, int index1, int index2); 757 758 // Compares the specified field on the two messages, returning 759 // true if they are the same, false otherwise. For repeated fields, 760 // this method only compares the value in the specified index. This method 761 // uses Compare functions to recurse into submessages. 762 // The parent_fields vector is used in calls to a Reporter instance calls. 763 // It can be NULL, in which case the MessageDifferencer will create new 764 // list of parent messages if it needs to recursively compare the given field. 765 // To avoid confusing users you should not set it to NULL unless you modified 766 // Reporter to handle the change of parent_fields correctly. 767 bool CompareFieldValueUsingParentFields( 768 const Message& message1, const Message& message2, 769 const FieldDescriptor* field, int index1, int index2, 770 std::vector<SpecificField>* parent_fields); 771 772 // Compares the specified field on the two messages, returning comparison 773 // result, as returned by appropriate FieldComparator. 774 FieldComparator::ComparisonResult GetFieldComparisonResult( 775 const Message& message1, const Message& message2, 776 const FieldDescriptor* field, int index1, int index2, 777 const FieldContext* field_context); 778 779 // Check if the two elements in the repeated field are match to each other. 780 // if the key_comprator is NULL, this function returns true when the two 781 // elements are equal. 782 bool IsMatch(const FieldDescriptor* repeated_field, 783 const MapKeyComparator* key_comparator, const Message* message1, 784 const Message* message2, 785 const std::vector<SpecificField>& parent_fields, 786 Reporter* reporter, int index1, int index2); 787 788 // Returns true when this repeated field has been configured to be treated 789 // as a Set / SmartSet / SmartList. 790 bool IsTreatedAsSet(const FieldDescriptor* field); 791 bool IsTreatedAsSmartSet(const FieldDescriptor* field); 792 793 bool IsTreatedAsSmartList(const FieldDescriptor* field); 794 // When treating as SMART_LIST, it uses MatchIndicesPostProcessorForSmartList 795 // by default to find the longest matching sequence from the first matching 796 // element. The callback takes two vectors showing the matching indices from 797 // the other vector, where -1 means an unmatch. 798 void SetMatchIndicesForSmartListCallback( 799 std::function<void(std::vector<int>*, std::vector<int>*)> callback); 800 801 // Returns true when this repeated field is to be compared as a subset, ie. 802 // has been configured to be treated as a set or map and scope is set to 803 // PARTIAL. 804 bool IsTreatedAsSubset(const FieldDescriptor* field); 805 806 // Returns true if this field is to be ignored when this 807 // MessageDifferencer compares messages. 808 bool IsIgnored(const Message& message1, const Message& message2, 809 const FieldDescriptor* field, 810 const std::vector<SpecificField>& parent_fields); 811 812 // Returns true if this unknown field is to be ignored when this 813 // MessageDifferencer compares messages. 814 bool IsUnknownFieldIgnored(const Message& message1, const Message& message2, 815 const SpecificField& field, 816 const std::vector<SpecificField>& parent_fields); 817 818 // Returns MapKeyComparator* when this field has been configured to be treated 819 // as a map or its is_map() return true. If not, returns NULL. 820 const MapKeyComparator* GetMapKeyComparator( 821 const FieldDescriptor* field) const; 822 823 // Attempts to match indices of a repeated field, so that the contained values 824 // match. Clears output vectors and sets their values to indices of paired 825 // messages, ie. if message1[0] matches message2[1], then match_list1[0] == 1 826 // and match_list2[1] == 0. The unmatched indices are indicated by -1. 827 // Assumes the repeated field is not treated as a simple list. 828 // This method returns false if the match failed. However, it doesn't mean 829 // that the comparison succeeds when this method returns true (you need to 830 // double-check in this case). 831 bool MatchRepeatedFieldIndices( 832 const Message& message1, const Message& message2, 833 const FieldDescriptor* repeated_field, 834 const MapKeyComparator* key_comparator, 835 const std::vector<SpecificField>& parent_fields, 836 std::vector<int>* match_list1, std::vector<int>* match_list2); 837 838 // If "any" is of type google.protobuf.Any, extract its payload using 839 // DynamicMessageFactory and store in "data". 840 bool UnpackAny(const Message& any, std::unique_ptr<Message>* data); 841 842 // Checks if index is equal to new_index in all the specific fields. 843 static bool CheckPathChanged(const std::vector<SpecificField>& parent_fields); 844 845 // CHECKs that the given repeated field can be compared according to 846 // new_comparison. 847 void CheckRepeatedFieldComparisons( 848 const FieldDescriptor* field, 849 const RepeatedFieldComparison& new_comparison); 850 851 // Defines a map between field descriptors and their MapKeyComparators. 852 // Used for repeated fields when they are configured as TreatAsMap. 853 typedef std::map<const FieldDescriptor*, const MapKeyComparator*> 854 FieldKeyComparatorMap; 855 856 // Defines a set to store field descriptors. Used for repeated fields when 857 // they are configured as TreatAsSet. 858 typedef std::set<const FieldDescriptor*> FieldSet; 859 typedef std::map<const FieldDescriptor*, RepeatedFieldComparison> FieldMap; 860 861 Reporter* reporter_; 862 DefaultFieldComparator default_field_comparator_; 863 FieldComparator* field_comparator_; 864 MessageFieldComparison message_field_comparison_; 865 Scope scope_; 866 RepeatedFieldComparison repeated_field_comparison_; 867 868 FieldMap repeated_field_comparisons_; 869 // Keeps track of MapKeyComparators that are created within 870 // MessageDifferencer. These MapKeyComparators should be deleted 871 // before MessageDifferencer is destroyed. 872 // When TreatAsMap or TreatAsMapWithMultipleFieldsAsKey is called, we don't 873 // store the supplied FieldDescriptors directly. Instead, a new 874 // MapKeyComparator is created for comparison purpose. 875 std::vector<MapKeyComparator*> owned_key_comparators_; 876 FieldKeyComparatorMap map_field_key_comparator_; 877 MapEntryKeyComparator map_entry_key_comparator_; 878 std::vector<IgnoreCriteria*> ignore_criteria_; 879 // Reused multiple times in RetrieveFields to avoid extra allocations 880 std::vector<const FieldDescriptor*> tmp_message_fields_; 881 882 FieldSet ignored_fields_; 883 884 bool report_matches_; 885 bool report_moves_; 886 bool report_ignores_; 887 888 std::string* output_string_; 889 890 // Callback to post-process the matched indices to support SMART_LIST. 891 std::function<void(std::vector<int>*, std::vector<int>*)> 892 match_indices_for_smart_list_callback_; 893 894 std::unique_ptr<DynamicMessageFactory> dynamic_message_factory_; 895 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageDifferencer); 896 }; 897 898 // This class provides extra information to the FieldComparator::Compare 899 // function. 900 class PROTOBUF_EXPORT FieldContext { 901 public: FieldContext(std::vector<MessageDifferencer::SpecificField> * parent_fields)902 explicit FieldContext( 903 std::vector<MessageDifferencer::SpecificField>* parent_fields) 904 : parent_fields_(parent_fields) {} 905 parent_fields()906 std::vector<MessageDifferencer::SpecificField>* parent_fields() const { 907 return parent_fields_; 908 } 909 910 private: 911 std::vector<MessageDifferencer::SpecificField>* parent_fields_; 912 }; 913 914 } // namespace util 915 } // namespace protobuf 916 } // namespace google 917 918 #include <google/protobuf/port_undef.inc> 919 920 #endif // GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__ 921