- Added regex support to expressions.
- Implmented configurable case sensitivity.
This commit is contained in:
Paul Beckingham
2011-06-21 18:07:12 -04:00
parent 8040ed5430
commit 03dbf7f468
4 changed files with 49 additions and 59 deletions

View File

@@ -34,6 +34,7 @@
#include <Duration.h> #include <Duration.h>
#include <Nibbler.h> #include <Nibbler.h>
#include <Variant.h> #include <Variant.h>
#include <RegX.h>
#include <text.h> #include <text.h>
#include <Expression.h> #include <Expression.h>
@@ -199,39 +200,15 @@ bool Expression::eval (Task& task)
else if (arg->first == "!~") else if (arg->first == "!~")
{ {
// std::cout << "# " << left.dump () << " !~ " << right.dump () << "\n"; // std::cout << "# " << left.dump () << " !~ " << right.dump () << "\n";
bool result = false; bool case_sensitive = context.config.getBoolean ("search.case.sensitive");
bool result = !eval_match (left, right, case_sensitive);
// Matches against description are really against either description, // Matches against description are really against either description,
// annotations or project. // annotations or project.
if (left._raw == "description") // Short-circuit if match already failed.
if (result && left._raw == "description")
{ {
if (right._raw_type == "rx") // TODO check further.
{
throw std::string ("rx not supported");
}
else
{
left.cast (Variant::v_string);
right.cast (Variant::v_string);
if (left._string.find (right._string) == std::string::npos)
result = true;
}
}
// Matches against non-description fields are treated as-is.
else
{
if (right._raw_type == "rx")
{
throw std::string ("rx not supported");
}
else
{
left.cast (Variant::v_string);
right.cast (Variant::v_string);
if (left._string.find (right._string) == std::string::npos)
result = true;
}
} }
left = Variant (result); left = Variant (result);
@@ -277,39 +254,15 @@ bool Expression::eval (Task& task)
else if (arg->first == "~") else if (arg->first == "~")
{ {
// std::cout << "# " << left.dump () << " ~ " << right.dump () << "\n"; // std::cout << "# " << left.dump () << " ~ " << right.dump () << "\n";
bool result = false; bool case_sensitive = context.config.getBoolean ("search.case.sensitive");
bool result = eval_match (left, right, case_sensitive);
// Matches against description are really against either description, // Matches against description are really against either description,
// annotations or project. // annotations or project.
if (left._raw == "description") // Short-circuit if match is already found.
if (!result && left._raw == "description")
{ {
if (right._raw_type == "rx") // TODO check further.
{
throw std::string ("rx not supported");
}
else
{
left.cast (Variant::v_string);
right.cast (Variant::v_string);
if (left._string.find (right._string) != std::string::npos)
result = true;
}
}
// Matches against non-description fields are treated as-is.
else
{
if (right._raw_type == "rx")
{
throw std::string ("rx not supported");
}
else
{
left.cast (Variant::v_string);
right.cast (Variant::v_string);
if (left._string.find (right._string) != std::string::npos)
result = true;
}
} }
left = Variant (result); left = Variant (result);
@@ -384,6 +337,32 @@ bool Expression::eval (Task& task)
return pass_fail; return pass_fail;
} }
////////////////////////////////////////////////////////////////////////////////
bool Expression::eval_match (Variant& left, Variant& right, bool case_sensitive)
{
if (right._raw_type == "rx")
{
left.cast (Variant::v_string);
right.cast (Variant::v_string);
// Create a cached entry, if it does not already exist.
if (_regexes.find (right._string) == _regexes.end ())
_regexes[right._string] = RegX (right._string, case_sensitive);
if (_regexes[right._string].match (left._string))
return true;
}
else
{
left.cast (Variant::v_string);
right.cast (Variant::v_string);
if (find (left._string, right._string, (bool) case_sensitive) != std::string::npos)
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void Expression::create_variant ( void Expression::create_variant (
Variant& variant, Variant& variant,

View File

@@ -32,6 +32,7 @@
#include <stack> #include <stack>
#include <Arguments.h> #include <Arguments.h>
#include <Task.h> #include <Task.h>
#include <RegX.h>
#include <Variant.h> #include <Variant.h>
class Expression class Expression
@@ -56,10 +57,11 @@ private:
bool is_new_style (); bool is_new_style ();
private: private:
bool eval_match (Variant&, Variant&, bool);
private: private:
Arguments _args; Arguments _args;
std::map <std::string, RegX> _regexes;
}; };
#endif #endif

View File

@@ -34,6 +34,14 @@
//#define _POSIX_C_SOURCE 1 //#define _POSIX_C_SOURCE 1
#define MAX_MATCHES 64 #define MAX_MATCHES 64
////////////////////////////////////////////////////////////////////////////////
RegX::RegX ()
: _compiled (false)
, _pattern ("")
, _case_sensitive (true)
{
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
RegX::RegX ( RegX::RegX (
const std::string& pattern, const std::string& pattern,

View File

@@ -36,6 +36,7 @@
class RegX class RegX
{ {
public: public:
RegX ();
RegX (const std::string&, bool caseSensitive = true); RegX (const std::string&, bool caseSensitive = true);
RegX (const RegX&); RegX (const RegX&);
RegX& operator= (const RegX&); RegX& operator= (const RegX&);