00001 #ifndef TAGCOLL_EXPRESSION_H
00002 #define TAGCOLL_EXPRESSION_H
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <tagcoll/Filter.h>
00025 #include <string>
00026 #include <map>
00027
00028 namespace Tagcoll
00029 {
00030
00031 class TagexprContext;
00032
00036 class ExpressionImpl
00037 {
00038 protected:
00039 int _ref;
00040
00041 public:
00042 ExpressionImpl() : _ref(0) {}
00043 virtual ~ExpressionImpl() {}
00044
00046 void ref() throw () { ++_ref; }
00047
00050 bool unref() throw () { return --_ref == 0; }
00051
00055 virtual std::string format() const = 0;
00056
00062 virtual bool eval(const TagexprContext& context) const = 0;
00063
00070 virtual bool eval(const OpSet<std::string>& tags) const = 0;
00071
00075
00076 };
00077
00078 class Expression
00079 {
00080 protected:
00081 ExpressionImpl* m_impl;
00082
00083 Expression(ExpressionImpl* impl) : m_impl(impl) { m_impl->ref(); }
00084
00085 const ExpressionImpl* impl() const { return m_impl; }
00086 ExpressionImpl* impl() { return m_impl; }
00087
00088 public:
00089 Expression();
00090 Expression(const std::string& expr);
00091
00092 Expression(const Expression& e)
00093 {
00094 if (e.m_impl)
00095 e.m_impl->ref();
00096 m_impl = e.m_impl;
00097 }
00098 ~Expression() { if (m_impl->unref()) delete m_impl; }
00099
00100 Expression& operator=(const Expression& e)
00101 {
00102 if (e.m_impl)
00103 e.m_impl->ref();
00104 if (m_impl && m_impl->unref())
00105 delete m_impl;
00106 m_impl = e.m_impl;
00107 return *this;
00108 }
00109
00110 Expression operator and (const Expression& e);
00111 Expression operator or (const Expression& e);
00112 Expression operator not ();
00113
00114 template<typename M>
00115 bool operator()(const OpSet<M>& tags) const { return m_impl->eval(tags); }
00116
00117 bool operator()(const TagexprContext& context) const { return m_impl->eval(context); }
00118
00119 std::string format() const { return m_impl->format(); }
00120
00121 static Expression matchTag(const std::string& pattern);
00122 };
00123
00136 class TagexprContext
00137 {
00138 protected:
00139 const OpSet<std::string>& tags;
00140 const std::map<std::string, Expression>& derivedTags;
00141
00142 mutable OpSet<std::string> seen;
00143
00144 public:
00158 TagexprContext(const OpSet<std::string>& tags, const std::map<std::string, Expression>& derivedTags)
00159 : tags(tags), derivedTags(derivedTags) {}
00160
00166 bool eval(const std::string& tag) const;
00167 };
00168
00169
00173 template<class ITEM, class TAG>
00174 class FilterItemsByExpression : public Filter<ITEM, TAG>
00175 {
00176 public:
00177 enum MatchType { PLAIN, INVERTED };
00178
00179 protected:
00180 Expression expr;
00181 MatchType matchType;
00182 int matched;
00183
00184 bool match(const OpSet<TAG>& tags) const
00185 {
00186 if (matchType == PLAIN)
00187 return expr(tags);
00188 else
00189 return !expr(tags);
00190
00191 }
00192
00193 virtual void consumeItemUntagged(const ITEM& item)
00194 {
00195 if (match(OpSet<TAG>()))
00196 {
00197 matched++;
00198 this->consumer->consume(item);
00199 }
00200 }
00201 virtual void consumeItem(const ITEM& item, const OpSet<TAG>& tags)
00202 {
00203 if (match(tags))
00204 {
00205 matched++;
00206 this->consumer->consume(item, tags);
00207 }
00208 }
00209 virtual void consumeItemsUntagged(const OpSet<ITEM>& items)
00210 {
00211 if (match(OpSet<TAG>()))
00212 {
00213 matched += items.size();
00214 this->consumer->consume(items);
00215 }
00216 }
00217 virtual void consumeItems(const OpSet<ITEM>& items, const OpSet<TAG>& tags)
00218 {
00219 if (match(tags))
00220 {
00221 matched += items.size();
00222 this->consumer->consume(items, tags);
00223 }
00224 }
00225
00226 public:
00227 FilterItemsByExpression(const Expression& expression) :
00228 expr(expression), matchType(PLAIN), matched(0) {}
00229 FilterItemsByExpression(const std::string& expression) :
00230 expr(expression), matchType(PLAIN), matched(0) {}
00231 FilterItemsByExpression(Consumer<ITEM, TAG>&cons, const Expression& expression) :
00232 Filter<ITEM, TAG>(cons),
00233 expr(expression), matchType(PLAIN), matched(0) {}
00234 FilterItemsByExpression(Consumer<ITEM, TAG>&cons, const std::string& expression) :
00235 Filter<ITEM, TAG>(cons),
00236 expr(expression), matchType(PLAIN), matched(0) {}
00237 virtual ~FilterItemsByExpression() {}
00238
00245 void setExpression(const Expression& expression)
00246 {
00247 expr = expression;
00248 }
00249
00256 void setExpression(const std::string& expression)
00257 {
00258 expr = Expression(expression);
00259 }
00260
00268 void setMatchType(MatchType type) { matchType = type; }
00269
00279 int countMatched() const { return matched; }
00280
00281 };
00282
00290 template<class ITEM, class TAG>
00291 class FilterTagsByExpression : public Filter<ITEM, TAG>
00292 {
00293 public:
00294 enum MatchType { PLAIN, INVERTED };
00295
00296 protected:
00297 Expression expr;
00298 MatchType matchType;
00299 int matched;
00300
00301 bool match(const TAG& tag) const
00302 {
00303 OpSet<TAG> tags;
00304 tags += tag;
00305 if (matchType == PLAIN)
00306 return expr(tags);
00307 else
00308 return !expr(tags);
00309 }
00310
00311 virtual void consumeItemUntagged(const ITEM& item)
00312 {
00313 this->consumer->consume(item);
00314 }
00315
00316 virtual void consumeItem(const ITEM& item, const OpSet<TAG>& tags)
00317 {
00318 OpSet<TAG> outTags;
00319 for (typename OpSet<TAG>::const_iterator i = tags.begin(); i != tags.end(); i++)
00320 if (match(*i))
00321 {
00322 matched++;
00323 outTags += *i;
00324 }
00325 this->consumer->consume(item, outTags);
00326 }
00327
00328 virtual void consumeItemsUntagged(const OpSet<ITEM>& items)
00329 {
00330 this->consumer->consume(items);
00331 }
00332
00333 virtual void consumeItems(const OpSet<ITEM>& items, const OpSet<TAG>& tags)
00334 {
00335 OpSet<TAG> outTags;
00336 for (typename OpSet<TAG>::const_iterator i = tags.begin();
00337 i != tags.end(); i++)
00338 if (match(*i))
00339 {
00340 matched += items.size();
00341 outTags += *i;
00342 }
00343 this->consumer->consume(items, outTags);
00344 }
00345
00346 public:
00347 FilterTagsByExpression(const Expression& expression) :
00348 expr(expression), matchType(PLAIN), matched(0) {}
00349 FilterTagsByExpression(const std::string& expression) :
00350 expr(expression), matchType(PLAIN), matched(0) {}
00351 FilterTagsByExpression(Consumer<ITEM, TAG>&cons, const Expression& expression) :
00352 Filter<ITEM, TAG>(cons),
00353 expr(expression), matchType(PLAIN), matched(0) {}
00354 FilterTagsByExpression(Consumer<ITEM, TAG>&cons, const std::string& expression) :
00355 Filter<ITEM, TAG>(cons),
00356 expr(expression), matchType(PLAIN), matched(0) {}
00357 virtual ~FilterTagsByExpression() {}
00358
00365 void setExpression(const Expression& expression)
00366 {
00367 expr = expression;
00368 }
00369
00376 void setExpression(const std::string& expression)
00377 {
00378 expr = Expression(expression);
00379 }
00380
00388 void setMatchType(MatchType type) { matchType = type; }
00389
00399 int countMatched() const { return matched; }
00400 };
00401
00402 };
00403
00404
00405 #endif