/*******************************************************************************
* libretroshare/src/retroshare: rsexpr.h *
* *
* libretroshare: retroshare core library *
* *
* Copyright 2007-2008 by Kashif Kaleem *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see . *
* *
*******************************************************************************/
#pragma once
#include
#include
#include
#include "util/rsprint.h"
#include "retroshare/rstypes.h"
#include "util/rstime.h"
/******************************************************************************************
Enumerations defining the Operators usable in the Boolean search expressions
******************************************************************************************/
namespace RsRegularExpression
{
enum LogicalOperator{
AndOp=0, /* exp AND exp */
OrOp=1, /* exp OR exp */
XorOp=2 /* exp XOR exp */
};
/* Operators for String Queries */
enum StringOperator{
ContainsAnyStrings = 0, /* e.g. name contains any of 'conference' 'meeting' 'presentation' */
ContainsAllStrings = 1, /* same as above except that it contains ALL of the strings */
EqualsString = 2 /* exactly equal*/
};
/* Comparison operators ( >, <, >=, <=, == and InRange ) */
enum RelOperator{
Equals = 0,
GreaterEquals = 1,
Greater = 2,
SmallerEquals = 3,
Smaller = 4,
InRange = 5 /* lower limit <= value <= upper limit*/
};
/********************************************************************************************
* Helper class for further serialisation
********************************************************************************************/
class StringExpression ;
class Expression ;
class LinearizedExpression
{
public:
std::vector _tokens ;
std::vector _ints ;
std::vector _strings ;
typedef enum { EXPR_DATE = 0,
EXPR_POP = 1,
EXPR_SIZE = 2,
EXPR_HASH = 3,
EXPR_NAME = 4,
EXPR_PATH = 5,
EXPR_EXT = 6,
EXPR_COMP = 7,
EXPR_SIZE_MB = 8 } token ;
static Expression *toExpr(const LinearizedExpression& e) ;
std::string GetStrings();
private:
static Expression *toExpr(const LinearizedExpression& e,int&,int&,int&) ;
static void readStringExpr(const LinearizedExpression& e,int& n_ints,int& n_strings,std::list& strings,bool& b,StringOperator& op) ;
};
/******************************************************************************************
Boolean Search Expression
classes:
Expression: The base class of all expression typest
CompoundExpression: The expression which uses a logical operator to combine
the results of two expressions
StringExpression: An expression which uses some sort of string comparison.
RelExpression: A Relational Expression where > < >= <= == make sense.
e.g. size date etc
******************************************************************************************/
/*!
* \brief The ExpFileEntry class
* This is the base class the regular expressions can operate on. Derive it to fit your own needs!
*/
class ExpFileEntry
{
public:
virtual const std::string& file_name() const =0;
virtual uint64_t file_size() const =0;
virtual rstime_t file_modtime() const =0;
virtual uint32_t file_popularity() const =0;
virtual std::string file_parent_path() const =0;
virtual const RsFileHash& file_hash() const =0;
};
class Expression
{
public:
virtual bool eval (const ExpFileEntry& file) = 0;
virtual ~Expression() {};
virtual void linearize(LinearizedExpression& e) const = 0 ;
virtual std::string toStdString() const = 0 ;
};
class CompoundExpression : public Expression
{
public:
CompoundExpression( enum LogicalOperator op, Expression * exp1, Expression *exp2)
: Lexp(exp1), Rexp(exp2), Op(op){ }
bool eval (const ExpFileEntry& file) {
if (Lexp == NULL or Rexp == NULL) {
return false;
}
switch (Op){
case AndOp:
return Lexp->eval(file) && Rexp->eval(file);
case OrOp:
return Lexp->eval(file) || Rexp->eval(file);
case XorOp:
return Lexp->eval(file) ^ Rexp->eval(file);
default:
return false;
}
}
virtual ~CompoundExpression(){
delete Lexp;
delete Rexp;
}
virtual std::string toStdString() const
{
switch(Op)
{
case AndOp: return "(" + Lexp->toStdString() + ") AND (" + Rexp->toStdString() +")" ;
case OrOp: return "(" + Lexp->toStdString() + ") OR (" + Rexp->toStdString() +")" ;
case XorOp: return "(" + Lexp->toStdString() + ") XOR (" + Rexp->toStdString() +")" ;
default:
return "" ;
}
}
virtual void linearize(LinearizedExpression& e) const ;
private:
Expression *Lexp;
Expression *Rexp;
enum LogicalOperator Op;
};
class StringExpression: public Expression
{
public:
StringExpression(enum StringOperator op, const std::list &t, bool ic): Op(op),terms(t), IgnoreCase(ic){}
virtual void linearize(LinearizedExpression& e) const ;
virtual std::string toStdStringWithParam(const std::string& varstr) const;
protected:
bool evalStr(const std::string &str);
enum StringOperator Op;
std::list terms;
bool IgnoreCase;
};
template
class RelExpression: public Expression
{
public:
RelExpression(enum RelOperator op, T lv, T hv): Op(op), LowerValue(lv), HigherValue(hv) {}
virtual void linearize(LinearizedExpression& e) const ;
virtual std::string toStdStringWithParam(const std::string& typestr) const;
protected:
bool evalRel(T val);
enum RelOperator Op;
T LowerValue;
T HigherValue;
};
template<> void RelExpression::linearize(LinearizedExpression& e) const ;
template
bool RelExpression::evalRel(T val) {
switch (Op) {
case Equals:
return LowerValue == val;
case GreaterEquals:
return LowerValue >= val;
case Greater:
return LowerValue > val;
case SmallerEquals:
return LowerValue <= val;
case Smaller:
return LowerValue < val;
case InRange:
return (LowerValue <= val) && (val <= HigherValue);
default:
return false;
}
}
template
std::string RelExpression::toStdStringWithParam(const std::string& typestr) const
{
std::string LowerValueStr = RsUtil::NumberToString(LowerValue) ;
switch (Op) {
case Equals: return typestr + " = " + LowerValueStr ;
case GreaterEquals: return typestr + " <= "+ LowerValueStr ;
case Greater: return typestr + " < " + LowerValueStr ;
case SmallerEquals: return typestr + " >= "+ LowerValueStr ;
case Smaller: return typestr + " > " + LowerValueStr ;
case InRange: return LowerValueStr + " <= " + typestr + " <= " + RsUtil::NumberToString(HigherValue) ;
default:
return "";
}
}
/******************************************************************************************
Binary Predicate for Case Insensitive search
******************************************************************************************/
/*Binary predicate for case insensitive character comparison.*/
/*TODOS:
*Factor locales in the comparison
*/
struct CompareCharIC :
public std::binary_function< char , char , bool> {
bool operator () ( char ch1 , char ch2 ) const {
return tolower( static_cast < unsigned char > (ch1) )
== tolower( static_cast < unsigned char > (ch2) );
}
};
/******************************************************************************************
Some implementations of StringExpressions.
******************************************************************************************/
class NameExpression: public StringExpression
{
public:
NameExpression(enum StringOperator op, const std::list &t, bool ic):
StringExpression(op,t,ic) {}
bool eval(const ExpFileEntry& file);
virtual std::string toStdString() const { return StringExpression::toStdStringWithParam("NAME"); }
virtual void linearize(LinearizedExpression& e) const
{
e._tokens.push_back(LinearizedExpression::EXPR_NAME) ;
StringExpression::linearize(e) ;
}
};
class PathExpression: public StringExpression {
public:
PathExpression(enum StringOperator op, const std::list &t, bool ic):
StringExpression(op,t,ic) {}
bool eval(const ExpFileEntry& file);
virtual std::string toStdString()const { return StringExpression::toStdStringWithParam("PATH"); }
virtual void linearize(LinearizedExpression& e) const
{
e._tokens.push_back(LinearizedExpression::EXPR_PATH) ;
StringExpression::linearize(e) ;
}
};
class ExtExpression: public StringExpression {
public:
ExtExpression(enum StringOperator op, const std::list &t, bool ic):
StringExpression(op,t,ic) {}
bool eval(const ExpFileEntry& file);
virtual std::string toStdString()const { return StringExpression::toStdStringWithParam("EXTENSION"); }
virtual void linearize(LinearizedExpression& e) const
{
e._tokens.push_back(LinearizedExpression::EXPR_EXT) ;
StringExpression::linearize(e) ;
}
};
class HashExpression: public StringExpression {
public:
HashExpression(enum StringOperator op, const std::list &t):
StringExpression(op,t, true) {}
bool eval(const ExpFileEntry& file);
virtual std::string toStdString() const { return StringExpression::toStdStringWithParam("HASH"); }
virtual void linearize(LinearizedExpression& e) const
{
e._tokens.push_back(LinearizedExpression::EXPR_HASH) ;
StringExpression::linearize(e) ;
}
};
/******************************************************************************************
Some implementations of Relational Expressions.
******************************************************************************************/
class DateExpression: public RelExpression
{
public:
DateExpression(enum RelOperator op, int v): RelExpression(op,v,v){}
DateExpression(enum RelOperator op, int lv, int hv):
RelExpression(op,lv,hv) {}
bool eval(const ExpFileEntry& file);
virtual std::string toStdString() const { return RelExpression::toStdStringWithParam("DATE"); }
virtual void linearize(LinearizedExpression& e) const
{
e._tokens.push_back(LinearizedExpression::EXPR_DATE) ;
RelExpression::linearize(e) ;
}
};
class SizeExpression: public RelExpression
{
public:
SizeExpression(enum RelOperator op, int v): RelExpression(op,v,v){}
SizeExpression(enum RelOperator op, int lv, int hv):
RelExpression(op,lv,hv) {}
bool eval(const ExpFileEntry& file);
virtual std::string toStdString() const { return RelExpression::toStdStringWithParam("SIZE"); }
virtual void linearize(LinearizedExpression& e) const
{
e._tokens.push_back(LinearizedExpression::EXPR_SIZE) ;
RelExpression::linearize(e) ;
}
};
class SizeExpressionMB: public RelExpression
{
public:
SizeExpressionMB(enum RelOperator op, int v): RelExpression(op,v,v){}
SizeExpressionMB(enum RelOperator op, int lv, int hv):
RelExpression(op,lv,hv) {}
bool eval(const ExpFileEntry& file);
virtual std::string toStdString() const { return RelExpression::toStdStringWithParam("SIZE"); }
virtual void linearize(LinearizedExpression& e) const
{
e._tokens.push_back(LinearizedExpression::EXPR_SIZE_MB) ;
RelExpression::linearize(e) ;
}
};
class PopExpression: public RelExpression
{
public:
PopExpression(enum RelOperator op, int v): RelExpression(op,v,v){}
PopExpression(enum RelOperator op, int lv, int hv): RelExpression(op,lv,hv) {}
PopExpression(const LinearizedExpression& e) ;
bool eval(const ExpFileEntry& file);
virtual std::string toStdString() const { return RelExpression::toStdStringWithParam("POPULARITY"); }
virtual void linearize(LinearizedExpression& e) const
{
e._tokens.push_back(LinearizedExpression::EXPR_POP) ;
RelExpression::linearize(e) ;
}
};
}