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>
45 class Query {
46  public:
47  typedef std::shared_ptr<
50  typedef std::vector<CHILD_TYPE> CHILD_VECT;
51  typedef typename CHILD_VECT::iterator CHILD_VECT_I;
52  typedef typename CHILD_VECT::const_iterator CHILD_VECT_CI;
53 
54  Query() : d_matchFunc(nullptr), d_dataFunc(nullptr){};
55  virtual ~Query() { this->d_children.clear(); };
56 
57  //! sets whether or not we are negated
58  void setNegation(bool what) { this->df_negate = what; };
59  //! returns whether or not we are negated
60  bool getNegation() const { return this->df_negate; };
61 
62  //! sets our text description
63  void setDescription(const std::string &descr) {
64  this->d_description = descr;
65  };
66  //! \overload
67  void setDescription(const char *descr) {
68  this->d_description = std::string(descr);
69  };
70  //! returns our text description
71  const std::string &getDescription() const { return this->d_description; };
72  //! returns a fuller text description
73  virtual std::string getFullDescription() const {
74  if (!getNegation())
75  return getDescription();
76  else
77  return "not " + getDescription();
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  if (this->getNegation())
119  return !tRes;
120  else
121  return tRes;
122  };
123 
124  //! returns a copy of this Query
125  /*!
126  <b>Notes:</b>
127  - the caller is responsible for <tt>delete</tt>ing the result
128  */
130  const {
133  for (auto iter = this->beginChildren(); iter != this->endChildren();
134  ++iter) {
135  res->addChild(CHILD_TYPE(iter->get()->copy()));
136  }
137  res->d_val = this->d_val;
138  res->d_tol = this->d_tol;
139  res->df_negate = this->df_negate;
140  res->d_matchFunc = this->d_matchFunc;
141  res->d_dataFunc = this->d_dataFunc;
142  res->d_description = this->d_description;
143  res->d_queryType = this->d_queryType;
144  return res;
145  };
146 
147  protected:
148  MatchFuncArgType d_val = 0;
149  MatchFuncArgType d_tol = 0;
150  std::string d_description = "";
151  std::string d_queryType = "";
153  bool df_negate{false};
154  bool (*d_matchFunc)(MatchFuncArgType);
155 
156  // MSVC complains at compile time when TypeConvert(MatchFuncArgType what,
157  // Int2Type<false>) attempts to pass what (which is of type MatchFuncArgType)
158  // as parameter of d_dataFunc() (which should be of type DataFuncArgType). The
159  // union is but a trick to avoid silly casts and keep MSVC happy when building
160  // DLLs
161  union {
162  MatchFuncArgType (*d_dataFunc)(DataFuncArgType);
163  MatchFuncArgType (*d_dataFuncSameType)(MatchFuncArgType);
164  };
165  //! \brief calls our \c dataFunc (if it's set) on \c what and returns
166  //! the result, otherwise returns \c what
167  MatchFuncArgType TypeConvert(MatchFuncArgType what,
168  Int2Type<false> /*d*/) const {
169  MatchFuncArgType mfArg;
170  if (this->d_dataFuncSameType != nullptr &&
171  std::is_same<MatchFuncArgType, DataFuncArgType>::value) {
172  mfArg = this->d_dataFuncSameType(what);
173  } else {
174  mfArg = what;
175  }
176  return mfArg;
177  }
178  //! calls our \c dataFunc (which must be set) on \c what and returns the
179  // result
180  MatchFuncArgType TypeConvert(DataFuncArgType what,
181  Int2Type<true> /*d*/) const {
182  PRECONDITION(this->d_dataFunc, "no data function");
183  MatchFuncArgType mfArg;
184  mfArg = this->d_dataFunc(what);
185  return mfArg;
186  }
187 };
188 
189 //----------------------------
190 //
191 // Used within query functions to compare values
192 //
193 //----------------------------
194 template <class T1, class T2>
195 int queryCmp(const T1 v1, const T2 v2, const T1 tol) {
196  T1 diff = v1 - v2;
197  if (diff <= tol) {
198  if (diff >= -tol) {
199  return 0;
200  } else {
201  return -1;
202  }
203  } else {
204  return 1;
205  }
206 };
207 } // namespace Queries
208 #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:162
MatchFuncArgType TypeConvert(DataFuncArgType what, Int2Type< true >) const
calls our dataFunc (which must be set) on what and returns the
Definition: Query.h:180
bool(*)(MatchFuncArgType) getMatchFunc() const
returns our match function:
Definition: Query.h:92
MatchFuncArgType(* d_dataFuncSameType)(MatchFuncArgType)
Definition: Query.h:163
virtual std::string getFullDescription() const
returns a fuller text description
Definition: Query.h:73
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:167
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:67
const std::string & getTypeLabel() const
returns our text label.
Definition: Query.h:85
std::shared_ptr< Query< MatchFuncArgType, DataFuncArgType, needsConversion > > CHILD_TYPE
Definition: Query.h:49
std::string d_queryType
Definition: Query.h:151
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:71
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
virtual Query< MatchFuncArgType, DataFuncArgType, needsConversion > * copy() const
returns a copy of this Query
Definition: Query.h:129
bool getNegation() const
returns whether or not we are negated
Definition: Query.h:60
void setNegation(bool what)
sets whether or not we are negated
Definition: Query.h:58
CHILD_VECT d_children
Definition: Query.h:152
CHILD_VECT::const_iterator CHILD_VECT_CI
Definition: Query.h:52
void setMatchFunc(bool(*what)(MatchFuncArgType))
sets our match function
Definition: Query.h:88
CHILD_VECT::iterator CHILD_VECT_I
Definition: Query.h:51
bool df_negate
Definition: Query.h:153
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:55
MatchFuncArgType d_tol
Definition: Query.h:149
std::vector< CHILD_TYPE > CHILD_VECT
Definition: Query.h:50
MatchFuncArgType d_val
Definition: Query.h:148
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:63
std::string d_description
Definition: Query.h:150
bool(* d_matchFunc)(MatchFuncArgType)
Definition: Query.h:154
int queryCmp(const T1 v1, const T2 v2, const T1 tol)
Definition: Query.h:195