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