RDKit
Open-source cheminformatics and machine learning.
Query.h
Go to the documentation of this file.
1 //
2 // Copyright (c) 2003-2020 Greg Landrum and Rational Discovery LLC
3 //
4 // @@ All Rights Reserved @@
5 // This file is part of the RDKit.
6 // The contents are covered by the terms of the BSD license
7 // which is included in the file license.txt, found at the root
8 // of the RDKit source tree.
9 //
10 #include <RDGeneral/export.h>
11 #ifndef RD_QUERY_H
12 #define RD_QUERY_H
13 
14 #ifdef _MSC_VER
15 #pragma warning(disable : 4800) // warning: converting things to bool
16 #endif
17 
18 #include <vector>
19 #include <string>
20 #include <RDGeneral/Invariant.h>
21 
22 namespace Queries {
23 
24 //! class to allow integer values to pick templates
25 template <int v>
26 class Int2Type {
27  enum { value = v };
28 };
29 
30 //! Base class for all queries
31 /*!
32  Query objects have one or two functions associated with them:
33  - <tt>bool matchFunc(MatchFuncArgType other)</tt> returns true or false
34  to indicate whether this query matches \c other.
35  This is mandatory.
36 
37  - <tt>MatchFuncArgType dataFunc(DataFuncArgType other)</tt> converts
38  the argument \c other from \c DataFuncArgType to \c MatchFuncArgType.
39  This is optional if \c DataFuncArgType is the same as (or implicitly
40  convertible to) \c MatchFuncArgType.
41 
42 */
43 template <class MatchFuncArgType, class DataFuncArgType = MatchFuncArgType,
44  bool needsConversion = false>
46  public:
47  using CHILD_TYPE = std::shared_ptr<
49  using CHILD_VECT = std::vector<CHILD_TYPE>;
50  using CHILD_VECT_I = typename CHILD_VECT::iterator;
51  using CHILD_VECT_CI = typename CHILD_VECT::const_iterator;
52  using MATCH_FUNC_ARG_TYPE = MatchFuncArgType;
53  using DATA_FUNC_ARG_TYPE = DataFuncArgType;
54 
55  Query() : d_matchFunc(nullptr), d_dataFunc(nullptr) {}
56  virtual ~Query() { this->d_children.clear(); }
57 
58  //! sets whether or not we are negated
59  void setNegation(bool what) { this->df_negate = what; }
60  //! returns whether or not we are negated
61  bool getNegation() const { return this->df_negate; }
62 
63  //! sets our text description
64  void setDescription(const std::string &descr) { this->d_description = descr; }
65  //! \overload
66  void setDescription(const char *descr) {
67  this->d_description = std::string(descr);
68  }
69  //! returns our text description
70  const std::string &getDescription() const { return this->d_description; }
71  //! returns a fuller text description
72  virtual std::string getFullDescription() const {
73  if (!getNegation()) {
74  return getDescription();
75  } else {
76  return "not " + getDescription();
77  }
78  }
79 
80  //! sets our type label
81  void setTypeLabel(const std::string &typ) { this->d_queryType = typ; }
82  //! \overload
83  void setTypeLabel(const char *typ) { this->d_queryType = std::string(typ); }
84  //! returns our text label.
85  const std::string &getTypeLabel() const { return this->d_queryType; }
86 
87  //! sets our match function
88  void setMatchFunc(bool (*what)(MatchFuncArgType)) {
89  this->d_matchFunc = what;
90  }
91  //! returns our match function:
92  bool (*getMatchFunc() const)(MatchFuncArgType) { return this->d_matchFunc; }
93  //! sets our data function
94  void setDataFunc(MatchFuncArgType (*what)(DataFuncArgType)) {
95  this->d_dataFunc = what;
96  }
97  //! returns our data function:
98  MatchFuncArgType (*getDataFunc() const)(DataFuncArgType) {
99  return this->d_dataFunc;
100  }
101 
102  //! adds a child to our list of children
103  void addChild(CHILD_TYPE child) { this->d_children.push_back(child); }
104  //! returns an iterator for the beginning of our child vector
105  CHILD_VECT_CI beginChildren() const { return this->d_children.begin(); }
106  //! returns an iterator for the end of our child vector
107  CHILD_VECT_CI endChildren() const { return this->d_children.end(); }
108 
109  //! returns whether or not we match the argument
110  virtual bool Match(const DataFuncArgType arg) const {
111  MatchFuncArgType mfArg = TypeConvert(arg, Int2Type<needsConversion>());
112  bool tRes;
113  if (this->d_matchFunc) {
114  tRes = this->d_matchFunc(mfArg);
115  } else {
116  tRes = static_cast<bool>(mfArg);
117  }
118 
119  if (this->getNegation()) {
120  return !tRes;
121  } else {
122  return tRes;
123  }
124  }
125 
126  //! returns a copy of this Query
127  /*!
128  <b>Notes:</b>
129  - the caller is responsible for <tt>delete</tt>ing the result
130  */
132  const {
135  for (auto iter = this->beginChildren(); iter != this->endChildren();
136  ++iter) {
137  res->addChild(CHILD_TYPE(iter->get()->copy()));
138  }
139  res->d_val = this->d_val;
140  res->d_tol = this->d_tol;
141  res->df_negate = this->df_negate;
142  res->d_matchFunc = this->d_matchFunc;
143  res->d_dataFunc = this->d_dataFunc;
144  res->d_description = this->d_description;
145  res->d_queryType = this->d_queryType;
146  return res;
147  }
148 
149  protected:
150  MatchFuncArgType d_val = 0;
151  MatchFuncArgType d_tol = 0;
152  std::string d_description = "";
153  std::string d_queryType = "";
155  bool df_negate{false};
156  bool (*d_matchFunc)(MatchFuncArgType);
157 
158  // MSVC complains at compile time when TypeConvert(MatchFuncArgType what,
159  // Int2Type<false>) attempts to pass what (which is of type MatchFuncArgType)
160  // as parameter of d_dataFunc() (which should be of type DataFuncArgType). The
161  // union is but a trick to avoid silly casts and keep MSVC happy when building
162  // DLLs
163  union {
164  MatchFuncArgType (*d_dataFunc)(DataFuncArgType);
165  MatchFuncArgType (*d_dataFuncSameType)(MatchFuncArgType);
166  };
167  //! \brief calls our \c dataFunc (if it's set) on \c what and returns
168  //! the result, otherwise returns \c what
169  MatchFuncArgType TypeConvert(MatchFuncArgType what,
170  Int2Type<false> /*d*/) const {
171  MatchFuncArgType mfArg;
172  if (this->d_dataFuncSameType != nullptr &&
173  std::is_same<MatchFuncArgType, DataFuncArgType>::value) {
174  mfArg = this->d_dataFuncSameType(what);
175  } else {
176  mfArg = what;
177  }
178  return mfArg;
179  }
180  //! calls our \c dataFunc (which must be set) on \c what and returns the
181  /// result
182  MatchFuncArgType TypeConvert(DataFuncArgType what,
183  Int2Type<true> /*d*/) const {
184  PRECONDITION(this->d_dataFunc, "no data function");
185  MatchFuncArgType mfArg;
186  mfArg = this->d_dataFunc(what);
187  return mfArg;
188  }
189 };
190 
191 //----------------------------
192 //
193 // Used within query functions to compare values
194 //
195 //----------------------------
196 template <class T1, class T2>
197 int queryCmp(const T1 v1, const T2 v2, const T1 tol) {
198  T1 diff = v1 - v2;
199  if (diff <= tol) {
200  if (diff >= -tol) {
201  return 0;
202  } else {
203  return -1;
204  }
205  } else {
206  return 1;
207  }
208 };
209 } // namespace Queries
210 #endif
#define PRECONDITION(expr, mess)
Definition: Invariant.h:109
class to allow integer values to pick templates
Definition: Query.h:26
Base class for all queries.
Definition: Query.h:45
MatchFuncArgType(* d_dataFunc)(DataFuncArgType)
Definition: Query.h:164
MatchFuncArgType TypeConvert(DataFuncArgType what, Int2Type< true >) const
Definition: Query.h:182
bool(*)(MatchFuncArgType) getMatchFunc() const
returns our match function:
Definition: Query.h:92
std::shared_ptr< Query< MatchFuncArgType, DataFuncArgType, needsConversion > > CHILD_TYPE
Definition: Query.h:48
virtual std::string getFullDescription() const
returns a fuller text description
Definition: Query.h:72
virtual bool Match(const DataFuncArgType arg) const
returns whether or not we match the argument
Definition: Query.h:110
MatchFuncArgType TypeConvert(MatchFuncArgType what, Int2Type< false >) const
calls our dataFunc (if it's set) on what and returns the result, otherwise returns what
Definition: Query.h:169
void addChild(CHILD_TYPE child)
adds a child to our list of children
Definition: Query.h:103
void setDescription(const char *descr)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: Query.h:66
const std::string & getTypeLabel() const
returns our text label.
Definition: Query.h:85
std::string d_queryType
Definition: Query.h:153
CHILD_VECT_CI endChildren() const
returns an iterator for the end of our child vector
Definition: Query.h:107
const std::string & getDescription() const
returns our text description
Definition: Query.h:70
MatchFuncArgType MATCH_FUNC_ARG_TYPE
Definition: Query.h:52
CHILD_VECT_CI beginChildren() const
returns an iterator for the beginning of our child vector
Definition: Query.h:105
void setDataFunc(MatchFuncArgType(*what)(DataFuncArgType))
sets our data function
Definition: Query.h:94
void setTypeLabel(const std::string &typ)
sets our type label
Definition: Query.h:81
std::vector< CHILD_TYPE > CHILD_VECT
Definition: Query.h:49
virtual Query< MatchFuncArgType, DataFuncArgType, needsConversion > * copy() const
returns a copy of this Query
Definition: Query.h:131
DataFuncArgType DATA_FUNC_ARG_TYPE
Definition: Query.h:53
bool getNegation() const
returns whether or not we are negated
Definition: Query.h:61
void setNegation(bool what)
sets whether or not we are negated
Definition: Query.h:59
CHILD_VECT d_children
Definition: Query.h:154
typename CHILD_VECT::const_iterator CHILD_VECT_CI
Definition: Query.h:51
void setMatchFunc(bool(*what)(MatchFuncArgType))
sets our match function
Definition: Query.h:88
bool df_negate
Definition: Query.h:155
void setTypeLabel(const char *typ)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: Query.h:83
virtual ~Query()
Definition: Query.h:56
typename CHILD_VECT::iterator CHILD_VECT_I
Definition: Query.h:50
MatchFuncArgType d_tol
Definition: Query.h:151
MatchFuncArgType d_val
Definition: Query.h:150
MatchFuncArgType(*)(DataFuncArgType) getDataFunc() const
returns our data function:
Definition: Query.h:98
void setDescription(const std::string &descr)
sets our text description
Definition: Query.h:64
std::string d_description
Definition: Query.h:152
bool(* d_matchFunc)(MatchFuncArgType)
Definition: Query.h:156
#define RDKIT_QUERY_EXPORT
Definition: export.h:557
int queryCmp(const T1 v1, const T2 v2, const T1 tol)
Definition: Query.h:197