1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef COMPONENTS_ZUCCHINI_IMPOSED_ENSEMBLE_MATCHER_H_
6 #define COMPONENTS_ZUCCHINI_IMPOSED_ENSEMBLE_MATCHER_H_
7 
8 #include <stddef.h>
9 
10 #include <string>
11 #include <vector>
12 
13 #include "components/zucchini/buffer_view.h"
14 #include "components/zucchini/element_detection.h"
15 #include "components/zucchini/ensemble_matcher.h"
16 
17 namespace zucchini {
18 
19 // A class to parse imposed match format, which is either an empty string (no
20 // imposed patch), or a string formatted as:
21 //   "#+#=#+#,#+#=#+#,..."  (e.g., "1+2=3+4", "1+2=3+4,5+6=7+8"),
22 // where "#+#=#+#" encodes a match as 4 unsigned integers:
23 //   [offset in "old", size in "old", offset in "new", size in "new"].
24 class ImposedMatchParser {
25  public:
26   enum Status {
27     kSuccess,
28     kInvalidDelimiter,
29     kParseError,
30     kOutOfBound,
31     kOverlapInNew,
32     kTypeMismatch,
33   };
34 
35   ImposedMatchParser();
36   ImposedMatchParser(const ImposedMatchParser&) = delete;
37   const ImposedMatchParser& operator=(const ImposedMatchParser&) = delete;
38   ~ImposedMatchParser();
39 
40   // Parses |imposed_matches| and writes the results to member variables.
41   // |old_image| and |new_image| are used for validation. Returns a Status value
42   // to signal success or various error modes. |detector| is used to validate
43   // Element types for matched pairs. This should only be called once for each
44   // instance.
45   Status Parse(std::string imposed_matches,
46                ConstBufferView old_image,
47                ConstBufferView new_image,
48                ElementDetector&& detector);
49 
num_identical()50   size_t num_identical() const { return num_identical_; }
mutable_matches()51   std::vector<ElementMatch>* mutable_matches() { return &matches_; }
mutable_bad_matches()52   std::vector<ElementMatch>* mutable_bad_matches() { return &bad_matches_; }
53 
54  private:
55   size_t num_identical_ = 0;
56   std::vector<ElementMatch> matches_;
57   // Stores "forgiven" bad matches, so the caller can impose matches for
58   // unsupported image types (which will simply be ignored). Note that imposing
59   // matches for known but incompatible image types would result in error.
60   std::vector<ElementMatch> bad_matches_;
61 };
62 
63 // An ensemble matcher that parses a format string that describes matches.
64 class ImposedEnsembleMatcher : public EnsembleMatcher {
65  public:
66   // |imposed_matches| specifies imposed maches, using a format described below.
67   // Validation is performed in RunMatch().
68   explicit ImposedEnsembleMatcher(const std::string& imposed_matches);
69   ImposedEnsembleMatcher(const ImposedEnsembleMatcher&) = delete;
70   const ImposedEnsembleMatcher& operator=(const ImposedEnsembleMatcher&) =
71       delete;
72   ~ImposedEnsembleMatcher() override;
73 
74   // EnsembleMatcher:
75   bool RunMatch(ConstBufferView old_image, ConstBufferView new_image) override;
76 
77  private:
78   const std::string imposed_matches_;
79 };
80 
81 }  // namespace zucchini
82 
83 #endif  // COMPONENTS_ZUCCHINI_IMPOSED_ENSEMBLE_MATCHER_H_
84