You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

239 lines
6.1 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2015-2023 KiCad Developers, see AUTHORS.txt for contributors.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, you may find one here:
  18. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  19. * or you may search the http://www.gnu.org website for the version 2 license,
  20. * or you may write to the Free Software Foundation, Inc.,
  21. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  22. */
  23. /**
  24. * @file eda_pattern_match.h
  25. * @brief Abstract pattern-matching tool and implementations.
  26. */
  27. #ifndef EDA_PATTERN_MATCH_H
  28. #define EDA_PATTERN_MATCH_H
  29. #include <vector>
  30. #include <map>
  31. #include <memory>
  32. #include <wx/string.h>
  33. #include <wx/regex.h>
  34. static const int EDA_PATTERN_NOT_FOUND = wxNOT_FOUND;
  35. /*
  36. * A structure for storing weighted search terms.
  37. *
  38. * NOTE: an exact match is scored at 8 * Score while a match at the start of the text is scored
  39. * at 2 * Score.
  40. */
  41. struct SEARCH_TERM
  42. {
  43. SEARCH_TERM( const wxString& aText, int aScore ) :
  44. Text( aText ),
  45. Score( aScore ),
  46. Normalized( false )
  47. {}
  48. wxString Text;
  49. int Score;
  50. bool Normalized;
  51. };
  52. /*
  53. * Interface for a pattern matcher, for which there are several implementations
  54. */
  55. class EDA_PATTERN_MATCH
  56. {
  57. public:
  58. struct FIND_RESULT
  59. {
  60. int start = EDA_PATTERN_NOT_FOUND;
  61. int length = 0;
  62. bool valid() const
  63. {
  64. return start != EDA_PATTERN_NOT_FOUND;
  65. }
  66. explicit operator bool() const
  67. {
  68. return valid();
  69. }
  70. };
  71. virtual ~EDA_PATTERN_MATCH() {}
  72. /**
  73. * Set the pattern against which candidates will be matched. If the pattern
  74. * can not be processed, returns false.
  75. */
  76. virtual bool SetPattern( const wxString& aPattern ) = 0;
  77. /**
  78. * Return the pattern passed to SetPattern().
  79. */
  80. virtual wxString const& GetPattern() const = 0;
  81. /**
  82. * Return the location and possibly length of a match iff a given candidate
  83. * string matches the set pattern.
  84. * Otherwise, return an invalid FIND_RESULT.
  85. */
  86. virtual FIND_RESULT Find( const wxString& aCandidate ) const = 0;
  87. };
  88. /*
  89. * Match simple substring
  90. */
  91. class EDA_PATTERN_MATCH_SUBSTR : public EDA_PATTERN_MATCH
  92. {
  93. public:
  94. virtual bool SetPattern( const wxString& aPattern ) override;
  95. virtual wxString const& GetPattern() const override;
  96. virtual FIND_RESULT Find( const wxString& aCandidate ) const override;
  97. protected:
  98. wxString m_pattern;
  99. };
  100. /*
  101. * Match regular expression
  102. */
  103. class EDA_PATTERN_MATCH_REGEX : public EDA_PATTERN_MATCH
  104. {
  105. public:
  106. virtual bool SetPattern( const wxString& aPattern ) override;
  107. virtual wxString const& GetPattern() const override;
  108. virtual FIND_RESULT Find( const wxString& aCandidate ) const override;
  109. protected:
  110. wxString m_pattern;
  111. wxRegEx m_regex;
  112. };
  113. class EDA_PATTERN_MATCH_REGEX_ANCHORED : public EDA_PATTERN_MATCH_REGEX
  114. {
  115. public:
  116. virtual bool SetPattern( const wxString& aPattern ) override;
  117. };
  118. class EDA_PATTERN_MATCH_WILDCARD : public EDA_PATTERN_MATCH_REGEX
  119. {
  120. public:
  121. virtual bool SetPattern( const wxString& aPattern ) override;
  122. virtual wxString const& GetPattern() const override;
  123. virtual FIND_RESULT Find( const wxString& aCandidate ) const override;
  124. protected:
  125. wxString m_wildcard_pattern;
  126. };
  127. class EDA_PATTERN_MATCH_WILDCARD_ANCHORED : public EDA_PATTERN_MATCH_WILDCARD
  128. {
  129. public:
  130. virtual bool SetPattern( const wxString& aPattern ) override;
  131. };
  132. /**
  133. * Relational match.
  134. *
  135. * Matches tokens of the format:
  136. *
  137. * key:value or key=value
  138. *
  139. * with search patterns of the format:
  140. *
  141. * key<value, key<=value, key=value, key>=value, key>value
  142. *
  143. * by parsing the value numerically and comparing.
  144. */
  145. class EDA_PATTERN_MATCH_RELATIONAL : public EDA_PATTERN_MATCH
  146. {
  147. public:
  148. virtual bool SetPattern( const wxString& aPattern ) override;
  149. virtual wxString const& GetPattern() const override;
  150. virtual FIND_RESULT Find( const wxString& aCandidate ) const override;
  151. int FindOne( const wxString& aCandidate ) const;
  152. protected:
  153. enum RELATION { LT, LE, EQ, GE, GT, ANY };
  154. wxString m_pattern;
  155. wxString m_key;
  156. RELATION m_relation;
  157. double m_value;
  158. static wxRegEx m_regex_description;
  159. static wxRegEx m_regex_search;
  160. static const std::map<wxString, double> m_units;
  161. };
  162. enum COMBINED_MATCHER_CONTEXT
  163. {
  164. CTX_LIBITEM,
  165. CTX_NETCLASS,
  166. CTX_SIGNAL,
  167. CTX_SEARCH
  168. };
  169. class EDA_COMBINED_MATCHER
  170. {
  171. public:
  172. EDA_COMBINED_MATCHER( const wxString& aPattern, COMBINED_MATCHER_CONTEXT aContext );
  173. /*
  174. * Look in all existing matchers, return the earliest match of any of
  175. * the existing.
  176. *
  177. * @param aTerm term to look for
  178. * @param aMatchersTriggered out: number of matcher that found the term
  179. * @param aPostion out: where the term was found, or EDA_PATTERN_NOT_FOUND
  180. *
  181. * @return true if any matchers found the term
  182. */
  183. bool Find( const wxString& aTerm, int& aMatchersTriggered, int& aPosition );
  184. bool Find( const wxString& aTerm );
  185. bool StartsWith( const wxString& aTerm );
  186. const wxString& GetPattern() const;
  187. int ScoreTerms( std::vector<SEARCH_TERM>& aWeightedTerms );
  188. private:
  189. // Add matcher if it can compile the pattern.
  190. void AddMatcher( const wxString& aPattern, std::unique_ptr<EDA_PATTERN_MATCH> aMatcher );
  191. std::vector<std::unique_ptr<EDA_PATTERN_MATCH>> m_matchers;
  192. wxString m_pattern;
  193. };
  194. #endif // EDA_PATTERN_MATCH_H