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
|
#ifndef CHAPTER15_H
#define CHAPTER15_H
namespace chapter15
{
class Query_base
{
friend class Query;
protected:
using line_no = chapter10::TextQuery::line_no;
Query_base() {}
virtual ~Query_base() = default;
private:
virtual chapter10::QueryResult eval(const chapter10::TextQuery &) const = 0;
virtual string rep() const = 0;
};
class Query
{
friend Query operator~(const Query &);
friend Query operator|(const Query &, const Query &);
friend Query operator&(const Query &, const Query &);
public:
Query(const string &);
Query(const Query &p): q(p.q), use(p.use) {++*use;}
Query &operator=(const Query &p);
chapter10::QueryResult eval(const chapter10::TextQuery &t) const {return q->eval(t);}
string rep() const {return q->rep();}
~Query()
{
if(--*use == 0)
{
delete q;
delete use;
}
}
private:
Query(Query_base *query): q(query), use(new unsigned(1)) {}
Query_base *q;
unsigned *use;
};
Query &Query::operator=(const Query &p)
{
++*p.use;
if(--*use == 0)
{
delete use;
delete q;
}
use = p.use;
q = p.q;
return *this;
}
class WordQuery: public Query_base
{
friend class Query;
WordQuery(const string &s): query_word(s) {}
chapter10::QueryResult eval(const chapter10::TextQuery &t) const
{return t.query(query_word);}
string rep() const {return query_word;}
string query_word;
};
inline Query::Query(const string &s): q(new WordQuery(s)), use(new unsigned(1)) {}
class BinaryQuery: public Query_base
{
protected:
BinaryQuery(const Query &l, const Query &r, string s):
lhs(l), rhs(r), opSym(s) {}
string rep() const
{
return "(" + lhs.rep() + " "
+ opSym + " "
+ rhs.rep() + ")";
}
Query lhs, rhs;
string opSym;
};
class AndQuery: public BinaryQuery
{
friend Query operator&(const Query &, const Query &);
AndQuery(const Query &left, const Query &right):
BinaryQuery(left, right, "&") {}
chapter10::QueryResult eval(const chapter10::TextQuery &) const;
};
inline Query operator&(const Query &lhs, const Query &rhs)
{
return new AndQuery(lhs, rhs);
}
chapter10::QueryResult
AndQuery::eval(const chapter10::TextQuery &text) const
{
auto left = lhs.eval(text), right = rhs.eval(text);
auto ret_lines = make_shared<set<line_no>>();
set_intersection(left.begin(), left.end(),
right.begin(), right.end(),
inserter(*ret_lines, ret_lines->begin()));
return chapter10::QueryResult(rep(), ret_lines, left.get_file());
}
class OrQuery: public BinaryQuery
{
friend Query operator|(const Query &, const Query &);
OrQuery(const Query &left, const Query &right):
BinaryQuery(left, right, "|") {}
chapter10::QueryResult eval(const chapter10::TextQuery &) const;
};
inline Query operator|(const Query &lhs, const Query &rhs)
{
return new OrQuery(lhs, rhs);
}
ostream &operator<<(ostream &os, const Query &query)
{
return os << query.rep();
}
chapter10::QueryResult OrQuery::eval(const chapter10::TextQuery &text) const
{
auto right = rhs.eval(text), left = lhs.eval(text);
auto ret_lines = make_shared<set<line_no>>(left.begin(), left.end());
ret_lines->insert(right.begin(), right.end());
return chapter10::QueryResult(rep(), ret_lines, left.get_file());
}
class NotQuery: public Query_base
{
friend Query operator~(const Query &);
NotQuery(const Query &q): query(q) {}
string rep() const {return "~(" + query.rep() + ")";}
chapter10::QueryResult eval(const chapter10::TextQuery &) const;
Query query;
};
inline Query operator~(const Query &operand)
{
return new NotQuery(operand);
}
chapter10::QueryResult
NotQuery::eval(const chapter10::TextQuery &text) const
{
auto result = query.eval(text);
auto ret_lines = make_shared<set<line_no>>();
auto beg = result.begin(), end = result.end();
auto sz = result.get_file()->size();
for(size_t n = 0; n != sz; ++n)
{
if(beg == end || *beg != n)
ret_lines->insert(n);
else if(beg != end)
++beg;
}
return chapter10::QueryResult(rep(), ret_lines, result.get_file());
}
}
#endif
|