~ubuntu-branches/ubuntu/trusty/tagcoll2/trusty-proposed

« back to all changes in this revision

Viewing changes to tagcoll/expression.cc

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Fontaine
  • Date: 2006-11-18 12:15:11 UTC
  • Revision ID: james.westby@ubuntu.com-20061118121511-nic9no49s64crb7i
Tags: upstream-2.0.4
ImportĀ upstreamĀ versionĀ 2.0.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Embed a tag expression in a class with proper copy semantics
 
3
 * Plus some filters based on tag expressions
 
4
 *
 
5
 * Copyright (C) 2003,2004,2005  Enrico Zini <enrico@debian.org>
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2.1 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with this library; if not, write to the Free Software
 
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 
20
 */
 
21
 
 
22
#include <tagcoll/expression.h>
 
23
 
 
24
#include <tagcoll/tagexpr/TagexprParser.h>
 
25
 
 
26
using namespace std;
 
27
 
 
28
namespace tagcoll {
 
29
 
 
30
class TagexprTrue : public ExpressionImpl
 
31
{
 
32
public:
 
33
        TagexprTrue() {}
 
34
        virtual ~TagexprTrue() {}
 
35
 
 
36
        virtual std::string format() const { return "*"; }
 
37
 
 
38
        virtual bool eval(const TagexprContext& context) const { return true; }
 
39
        virtual bool eval(const std::set<std::string>& tags) const { return true; }
 
40
};
 
41
 
 
42
class TagexprTag : public ExpressionImpl
 
43
{
 
44
protected:
 
45
        std::string _tag;
 
46
        
 
47
public:
 
48
        TagexprTag(const std::string& tag) : _tag(tag) {}
 
49
        virtual ~TagexprTag() {}
 
50
 
 
51
        virtual std::string format() const { return _tag; }
 
52
 
 
53
        virtual bool eval(const TagexprContext& context) const
 
54
        {
 
55
                return context.eval(_tag);
 
56
        }
 
57
        virtual bool eval(const std::set<std::string>& tags) const
 
58
        {
 
59
                if (_tag[0] == '*')
 
60
                {
 
61
                        string match = _tag.substr(1);
 
62
                        for (std::set<string>::const_iterator i = tags.begin();
 
63
                                        i != tags.end(); i++)
 
64
                                if (i->size() >= match.size() &&
 
65
                                                i->substr(i->size() - match.size()) == match)
 
66
                                        return true;
 
67
                        return false;
 
68
                }
 
69
                else if (_tag[_tag.size() - 1] == '*')
 
70
                {
 
71
                        string match = _tag.substr(0, _tag.size() - 1);
 
72
                        for (std::set<string>::const_iterator i = tags.begin();
 
73
                                        i != tags.end(); i++)
 
74
                                if (i->size() >= match.size() &&
 
75
                                                i->substr(0, match.size()) == match)
 
76
                                        return true;
 
77
                        return false;
 
78
                }
 
79
                else
 
80
                        return tags.find(_tag) != tags.end();
 
81
        }
 
82
};
 
83
 
 
84
class TagexprNot : public ExpressionImpl
 
85
{
 
86
protected:
 
87
        Expression _op;
 
88
 
 
89
public:
 
90
        TagexprNot(const Expression& operand) : _op(operand) {}
 
91
 
 
92
        virtual std::string format() const { return "!" + _op.format(); }
 
93
 
 
94
        virtual bool eval(const TagexprContext& context) const
 
95
        {
 
96
                return ! _op(context);
 
97
        }
 
98
        virtual bool eval(const std::set<std::string>& tags) const
 
99
        {
 
100
                return ! _op(tags);
 
101
        }
 
102
};
 
103
 
 
104
class TagexprAnd : public ExpressionImpl
 
105
{
 
106
protected:
 
107
        Expression _op1;
 
108
        Expression _op2;
 
109
 
 
110
public:
 
111
        TagexprAnd(const Expression& operand1, const Expression& operand2)
 
112
                : _op1(operand1), _op2(operand2) {}
 
113
 
 
114
        virtual std::string format() const
 
115
        {
 
116
                return "( " + _op1.format() + " && " + _op2.format() + " )";
 
117
        }
 
118
 
 
119
        virtual bool eval(const TagexprContext& context) const
 
120
        {
 
121
                return _op1(context) && _op2(context);
 
122
        }
 
123
        virtual bool eval(const std::set<std::string>& tags) const
 
124
        {
 
125
                return _op1(tags) && _op2(tags);
 
126
        }
 
127
};
 
128
 
 
129
class TagexprOr : public ExpressionImpl
 
130
{
 
131
protected:
 
132
        Expression _op1;
 
133
        Expression _op2;
 
134
 
 
135
public:
 
136
        TagexprOr(const Expression& operand1, const Expression& operand2)
 
137
                : _op1(operand1), _op2(operand2) {}
 
138
        
 
139
        virtual std::string format() const
 
140
        {
 
141
                return "( " + _op1.format() + " || " + _op2.format() + " )";
 
142
        }
 
143
 
 
144
        virtual bool eval(const TagexprContext& context) const
 
145
        {
 
146
                return _op1(context) || _op2(context);
 
147
        }
 
148
        virtual bool eval(const std::set<std::string>& tags) const
 
149
        {
 
150
                return _op1(tags) || _op2(tags);
 
151
        }
 
152
};
 
153
 
 
154
 
 
155
Expression::Expression(const std::string& expr) : m_impl(0)
 
156
{
 
157
        Expression e = TagexprParser::instance()->parse(expr);
 
158
        
 
159
        m_impl = e.impl();
 
160
        m_impl->ref();
 
161
}
 
162
 
 
163
Expression::Expression() : m_impl(new TagexprTrue) { m_impl->ref(); }
 
164
 
 
165
Expression Expression::matchTag(const std::string& pattern)
 
166
{
 
167
        return Expression(new TagexprTag(pattern));
 
168
}
 
169
 
 
170
Expression Expression::operator and (const Expression& e)
 
171
{
 
172
        return Expression(new TagexprAnd(*this, e));
 
173
}
 
174
 
 
175
Expression Expression::operator or (const Expression& e)
 
176
{
 
177
        return Expression(new TagexprOr(*this, e));
 
178
}
 
179
 
 
180
Expression Expression::operator not ()
 
181
{
 
182
        return Expression(new TagexprNot(*this));
 
183
}
 
184
 
 
185
 
 
186
bool TagexprContext::eval(const std::string& tag) const
 
187
{
 
188
        std::map<std::string, Expression>::const_iterator i = derivedTags.find(tag);
 
189
        if (i == derivedTags.end())
 
190
                return tags.find(tag) != tags.end();
 
191
        else if (seen.find(tag) == seen.end())
 
192
        {
 
193
                seen.insert(tag);
 
194
                bool res = i->second(*this);
 
195
                seen.erase(tag);
 
196
                return res;
 
197
        }
 
198
        else
 
199
                // If we got here, we have a circular dependency between derived tags
 
200
                // FIXME: find a better way to handle it: throw an exception, maybe?
 
201
                return false;
 
202
}
 
203
 
 
204
}
 
205
 
 
206
// vim:set ts=4 sw=4: