RDKit
Open-source cheminformatics and machine learning.
Loading...
Searching...
No Matches
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
22namespace Queries {
23
24//! class to allow integer values to pick templates
25template <int v>
26class 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*/
43template <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//----------------------------
196template <class T1, class T2>
197int 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
const std::string & getTypeLabel() const
returns our text label.
Definition Query.h:85
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
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
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
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
virtual Query< MatchFuncArgType, DataFuncArgType, needsConversion > * copy() const
returns a copy of this Query
Definition Query.h:131
CHILD_VECT d_children
Definition Query.h:154
const std::string & getDescription() const
returns our text description
Definition Query.h:70
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:629
int queryCmp(const T1 v1, const T2 v2, const T1 tol)
Definition Query.h:197