forked from Mooophy/Cpp-Primer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
query.h
207 lines (177 loc) · 4.98 KB
/
query.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#ifndef QUERY_H
#define QUERY_H
#include <iostream>
#include <string>
#include <memory>
#include "textquery.h"
/**
* @brief abstract class acts as a base class for all concrete query types
* all members are private.
*/
class Query_base
{
friend class Query;
protected:
using line_no = TextQuery::line_no; // used in the eval function
virtual ~Query_base() = default;
private:
// returns QueryResult that matches this query
virtual QueryResult eval(const TextQuery&) const = 0;
// a string representation of this query
virtual std::string rep() const = 0;
};
/**
* @brief The WordQuery class
*The only class that actually performs a query on the given TextQuery object.
*No public members defined in this class. All operation are through the friend
*class Query.
*/
class WordQuery : public Query_base
{
// class Query uses the WordQuery constructor
friend class Query;
WordQuery(const std::string& s):
query_word(s)
{
std::cout << "WordQuery::WordQuery(" + s + ")\n";
}
// virtuals:
QueryResult eval(const TextQuery& t) const override
{ return t.query(query_word); }
std::string rep() const override
{
std::cout << "WodQuery::rep()\n";
return query_word;
}
std::string query_word;
};
/**
* @brief interface class to manage the Query_base inheritance hierachy
*/
class Query
{
friend Query operator~(const Query&);
friend Query operator|(const Query&, const Query&);
friend Query operator&(const Query&, const Query&);
public:
// build a new WordQuery
Query(const std::string& s) : q(new WordQuery(s))
{
std::cout << "Query::Query(const std::string& s) where s="+s+"\n";
}
// interface functions: call the corresponding Query_base operatopns
QueryResult eval(const TextQuery& t) const
{ return q->eval(t); }
std::string rep() const
{
std::cout << "Query::rep() \n";
return q->rep();
}
private:
// constructor only for friends
Query(std::shared_ptr<Query_base> query) :
q(query)
{
std::cout << "Query::Query(std::shared_ptr<Query_base> query)\n";
}
std::shared_ptr<Query_base> q;
};
inline std::ostream&
operator << (std::ostream& os, const Query& query)
{
// make a virtual call through its Query_base pointer to rep();
return os << query.rep();
}
/**
* @brief The BinaryQuery class
*An abstract class holds data needed by the query types that operate on two operands
*/
class BinaryQuery : public Query_base
{
protected:
BinaryQuery(const Query&l, const Query& r, std::string s):
lhs(l), rhs(r), opSym(s)
{
std::cout << "BinaryQuery::BinaryQuery() where s=" + s + "\n";
}
// @note: abstract class: BinaryQuery doesn't define eval
std::string rep() const override
{
std::cout << "BinaryQuery::rep()\n";
return "(" + lhs.rep() + " "
+ opSym + " "
+ rhs.rep() + ")";
}
Query lhs, rhs;
std::string opSym;
};
/**
* @brief The OrQuery class
*
*The & operator generates a OrQuery, which held by a Query,
*/
class OrQuery :public BinaryQuery
{
friend Query operator|(const Query&, const Query&);
OrQuery(const Query& left, const Query& right):
BinaryQuery(left, right, "|")
{
std::cout << "OrQuery::OrQuery\n";
}
QueryResult eval(const TextQuery& )const override;
};
inline Query operator|(const Query &lhs, const Query& rhs)
{
return std::shared_ptr<Query_base>(new OrQuery(lhs, rhs));
}
/**
* @brief The AndQuery class
*
*The & operator generates a AndQuery, which held by a Query,
*/
class AndQuery : public BinaryQuery
{
friend Query operator&(const Query&, const Query&);
AndQuery(const Query& left, const Query& right):
BinaryQuery(left, right, "&")
{
std::cout << "AndQuery::AndQuery()\n";
}
// @note: inherits rep and define eval
QueryResult eval(const TextQuery &) const override;
};
inline Query operator& (const Query& lhs, const Query& rhs)
{
return std::shared_ptr<Query_base>(new AndQuery(lhs, rhs));
}
/**
* @brief The NotQuery class
*
*The ~ operator generates a NotQuery, which held by a Query,
*which it negates.
*/
class NotQuery : public Query_base
{
friend Query operator~(const Query& operand);
NotQuery(const Query& q): query(q)
{
std::cout << "NotQuery::NotQuery()\n";
}
// virtuals:
std::string rep() const override
{
std::cout << "NotQuery::rep()\n";
return "~(" + query.rep() + ")";
}
QueryResult eval(const TextQuery &) const override;
Query query;
};
inline Query operator~(const Query& operand)
{
return std::shared_ptr<Query_base>(new NotQuery(operand));
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// note : There is an imlplicit conversion here.
// The Query constructor that takes shared_ptr is not
// "explicit", thus the compiler allows this conversion.
}
#endif // QUERY_H