message_differencer.h 38 KB

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