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  //! sets our type label
80  void setTypeLabel(const std::string &typ) { this->d_queryType = typ; }
81  //! \overload
82  void setTypeLabel(const char *typ) { this->d_queryType = std::string(typ); }
83  //! returns our text label.
84  const std::string &getTypeLabel() const { return this->d_queryType; }
85 
86  //! sets our match function
87  void setMatchFunc(bool (*what)(MatchFuncArgType)) {
88  this->d_matchFunc = what;
89  }
90  //! returns our match function:
91  bool (*getMatchFunc() const)(MatchFuncArgType) { return this->d_matchFunc; }
92  //! sets our data function
93  void setDataFunc(MatchFuncArgType (*what)(DataFuncArgType)) {
94  this->d_dataFunc = what;
95  }
96  //! returns our data function:
97  MatchFuncArgType (*getDataFunc() const)(DataFuncArgType) {
98  return this->d_dataFunc;
99  }
100 
101  //! adds a child to our list of children
102  void addChild(CHILD_TYPE child) { this->d_children.push_back(child); }
103  //! returns an iterator for the beginning of our child vector
104  CHILD_VECT_CI beginChildren() const { return this->d_children.begin(); }
105  //! returns an iterator for the end of our child vector
106  CHILD_VECT_CI endChildren() const { return this->d_children.end(); }
107 
108  //! returns whether or not we match the argument
109  virtual bool Match(const DataFuncArgType arg) const {
110  MatchFuncArgType mfArg = TypeConvert(arg, Int2Type<needsConversion>());
111  bool tRes;
112  if (this->d_matchFunc)
113  tRes = this->d_matchFunc(mfArg);
114  else
115  tRes = static_cast<bool>(mfArg);
116 
117  if (this->getNegation())
118  return !tRes;
119  else
120  return tRes;
121  }
122 
123  //! returns a copy of this Query
124  /*!
125  <b>Notes:</b>
126  - the caller is responsible for <tt>delete</tt>ing the result
127  */
129  const {
132  for (auto iter = this->beginChildren(); iter != this->endChildren();
133  ++iter) {
134  res->addChild(CHILD_TYPE(iter->get()->copy()));
135  }
136  res->d_val = this->d_val;
137  res->d_tol = this->d_tol;
138  res->df_negate = this->df_negate;
139  res->d_matchFunc = this->d_matchFunc;
140  res->d_dataFunc = this->d_dataFunc;
141  res->d_description = this->d_description;
142  res->d_queryType = this->d_queryType;
143  return res;
144  }
145 
146  protected:
147  MatchFuncArgType d_val = 0;
148  MatchFuncArgType d_tol = 0;
149  std::string d_description = "";
150  std::string d_queryType = "";
152  bool df_negate{false};
153  bool (*d_matchFunc)(MatchFuncArgType);
154 
155  // MSVC complains at compile time when TypeConvert(MatchFuncArgType what,
156  // Int2Type<false>) attempts to pass what (which is of type MatchFuncArgType)
157  // as parameter of d_dataFunc() (which should be of type DataFuncArgType). The
158  // union is but a trick to avoid silly casts and keep MSVC happy when building
159  // DLLs
160  union {
161  MatchFuncArgType (*d_dataFunc)(DataFuncArgType);
162  MatchFuncArgType (*d_dataFuncSameType)(MatchFuncArgType);
163  };
164  //! \brief calls our \c dataFunc (if it's set) on \c what and returns
165  //! the result, otherwise returns \c what
166  MatchFuncArgType TypeConvert(MatchFuncArgType what,
167  Int2Type<false> /*d*/) const {
168  MatchFuncArgType mfArg;
169  if (this->d_dataFuncSameType != nullptr &&
170  std::is_same<MatchFuncArgType, DataFuncArgType>::value) {
171  mfArg = this->d_dataFuncSameType(what);
172  } else {
173  mfArg = what;
174  }
175  return mfArg;
176  }
177  //! calls our \c dataFunc (which must be set) on \c what and returns the
178  /// result
179  MatchFuncArgType TypeConvert(DataFuncArgType what,
180  Int2Type<true> /*d*/) const {
181  PRECONDITION(this->d_dataFunc, "no data function");
182  MatchFuncArgType mfArg;
183  mfArg = this->d_dataFunc(what);
184  return mfArg;
185  }
186 };
187 
188 //----------------------------
189 //
190 // Used within query functions to compare values
191 //
192 //----------------------------
193 template <class T1, class T2>
194 int queryCmp(const T1 v1, const T2 v2, const T1 tol) {
195  T1 diff = v1 - v2;
196  if (diff <= tol) {
197  if (diff >= -tol) {
198  return 0;
199  } else {
200  return -1;
201  }
202  } else {
203  return 1;
204  }
205 };
206 } // namespace Queries
207 #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:161
MatchFuncArgType TypeConvert(DataFuncArgType what, Int2Type< true >) const
Definition: Query.h:179
bool(*)(MatchFuncArgType) getMatchFunc() const
returns our match function:
Definition: Query.h:91
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:109
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:166
void addChild(CHILD_TYPE child)
adds a child to our list of children
Definition: Query.h:102
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:84
std::string d_queryType
Definition: Query.h:150
CHILD_VECT_CI endChildren() const
returns an iterator for the end of our child vector
Definition: Query.h:106
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:104
void setDataFunc(MatchFuncArgType(*what)(DataFuncArgType))
sets our data function
Definition: Query.h:93
void setTypeLabel(const std::string &typ)
sets our type label
Definition: Query.h:80
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:128
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:151
typename CHILD_VECT::const_iterator CHILD_VECT_CI
Definition: Query.h:51
void setMatchFunc(bool(*what)(MatchFuncArgType))
sets our match function
Definition: Query.h:87
bool df_negate
Definition: Query.h:152
void setTypeLabel(const char *typ)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: Query.h:82
virtual ~Query()
Definition: Query.h:56
typename CHILD_VECT::iterator CHILD_VECT_I
Definition: Query.h:50
MatchFuncArgType d_tol
Definition: Query.h:148
MatchFuncArgType d_val
Definition: Query.h:147
MatchFuncArgType(*)(DataFuncArgType) getDataFunc() const
returns our data function:
Definition: Query.h:97
void setDescription(const std::string &descr)
sets our text description
Definition: Query.h:64
std::string d_description
Definition: Query.h:149
bool(* d_matchFunc)(MatchFuncArgType)
Definition: Query.h:153
#define RDKIT_QUERY_EXPORT
Definition: export.h:549
int queryCmp(const T1 v1, const T2 v2, const T1 tol)
Definition: Query.h:194