Implement regex() and match() functions.

Refs #5789
This commit is contained in:
Gunnar Beutner 2014-03-19 10:51:09 +01:00
parent 124fa9ebc1
commit 3383951791
9 changed files with 141 additions and 52 deletions

View File

@ -320,7 +320,7 @@ Simple calculations can be performed using the constant expression syntax:
check_interval = 30 + 60
}
Valid operators include ~, +, -, *, /, ==, !=, in and !in. The default precedence rules can be
Valid operators include ~, !, +, -, *, /, ==, !=, in and !in. The default precedence rules can be
overridden by grouping expressions using parentheses:
{

View File

@ -136,6 +136,11 @@ std::string& String::GetData(void)
return m_Data;
}
const std::string& String::GetData(void) const
{
return m_Data;
}
size_t String::Find(const String& str, size_t pos) const
{
return m_Data.find(str, pos);

View File

@ -80,6 +80,7 @@ public:
size_t GetLength(void) const;
std::string& GetData(void);
const std::string& GetData(void) const;
size_t Find(const String& str, size_t pos = 0) const;
size_t RFind(const String& str, size_t pos = NPos) const;

View File

@ -21,6 +21,7 @@
#include "base/array.h"
#include "base/serializer.h"
#include "base/context.h"
#include "base/scriptfunction.h"
#include <boost/foreach.hpp>
using namespace icinga;
@ -35,14 +36,19 @@ AExpression::AExpression(AOperator op, const AValue& operand1, const AValue& ope
: m_Operator(op), m_Operand1(operand1), m_Operand2(operand2), m_DebugInfo(di)
{
ASSERT(op == AEAdd || op == AENegate || op == AESubtract || op == AEMultiply || op == AEDivide ||
op == AEBinaryAnd || op == AEBinaryOr || op == AEShiftLeft || op == AEShiftRight);
op == AEBinaryAnd || op == AEBinaryOr || op == AEShiftLeft || op == AEShiftRight ||
op == AEEqual || op == AENotEqual || op == AEIn || op == AENotIn ||
op == AELogicalAnd || op == AELogicalOr || op == AEFunctionCall);
}
Value AExpression::Evaluate(const Dictionary::Ptr& locals) const
{
Value left, right;
Array::Ptr arr;
Array::Ptr arr, arr2;
bool found;
String funcName;
ScriptFunction::Ptr func;
std::vector<Value> arguments;
left = m_Operand1.Evaluate(locals);
right = m_Operand2.Evaluate(locals);
@ -111,8 +117,29 @@ Value AExpression::Evaluate(const Dictionary::Ptr& locals) const
return (long)left && (long)right;
case AELogicalOr:
return (long)left || (long)right;
case AEFunctionCall:
funcName = left;
func = ScriptFunctionRegistry::GetInstance()->GetItem(funcName);
if (!func)
BOOST_THROW_EXCEPTION(std::invalid_argument("Function '" + funcName + "' does not exist."));
arr = right;
BOOST_FOREACH(const AExpression::Ptr& aexpr, arr) {
arguments.push_back(aexpr->Evaluate(locals));
}
return func->Invoke(arguments);
case AEArray:
arr = left;
arr2 = make_shared<Array>();
BOOST_FOREACH(const AExpression::Ptr& aexpr, arr) {
arr2->Add(aexpr->Evaluate(locals));
}
return arr2;
default:
ASSERT(!"Invalid operator.");
}
}

View File

@ -48,7 +48,9 @@ enum AOperator
AEIn,
AENotIn,
AELogicalAnd,
AELogicalOr
AELogicalOr,
AEFunctionCall,
AEArray
};
/**

View File

@ -108,10 +108,8 @@ using namespace icinga;
%token T_TO "to (T_TO)"
%token T_WHERE "where (T_WHERE)"
%type <text> identifier
%type <array> array
%type <array> array_items
%type <array> array_items_inner
%type <variant> simplevalue
%type <variant> value
%type <expr> expression
%type <exprl> expressions
@ -135,6 +133,8 @@ using namespace icinga;
%left '*' '/'
%left '&'
%left '|'
%right '~'
%right '!'
%{
int yylex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner);
@ -506,12 +506,6 @@ operator: T_SET
}
;
array: '[' array_items ']'
{
$$ = $2;
}
;
array_items: array_items_inner
{
$$ = $1;
@ -525,79 +519,62 @@ array_items_inner: /* empty */
{
$$ = NULL;
}
| value
| aexpression
{
$$ = new Array();
if ($1->IsObjectType<ExpressionList>()) {
ExpressionList::Ptr exprl = *$1;
Dictionary::Ptr dict = make_shared<Dictionary>();
exprl->Execute(dict);
delete $1;
$1 = new Value(dict);
}
$$->Add(*$1);
delete $1;
}
| array_items_inner ',' value
| array_items_inner ',' aexpression
{
if ($1)
$$ = $1;
else
$$ = new Array();
if ($3->IsObjectType<ExpressionList>()) {
ExpressionList::Ptr exprl = *$3;
Dictionary::Ptr dict = make_shared<Dictionary>();
exprl->Execute(dict);
delete $3;
$3 = new Value(dict);
}
$$->Add(*$3);
delete $3;
}
;
simplevalue: T_STRING
aexpression: T_STRING
{
$$ = new Value($1);
$$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATSimple, $1), yylloc));
free($1);
}
| T_NUMBER
{
$$ = new Value($1);
$$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATSimple, $1), yylloc));
}
| T_NULL
{
$$ = new Value();
$$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATSimple, Empty), yylloc));
}
| array
| T_IDENTIFIER '(' array_items ')'
{
if ($1 == NULL)
$1 = new Array();
Array::Ptr array = Array::Ptr($1);
$$ = new Value(array);
}
;
aexpression: simplevalue
{
$$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATSimple, *$1), yylloc));
delete $1;
Array::Ptr arguments = Array::Ptr($3);
$$ = new Value(make_shared<AExpression>(AEFunctionCall, AValue(ATSimple, $1), AValue(ATSimple, arguments), yylloc));
free($1);
}
| T_IDENTIFIER
{
$$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATVariable, $1), yylloc));
free($1);
}
| '!' aexpression
{
$$ = new Value(make_shared<AExpression>(AENegate, static_cast<AExpression::Ptr>(*$2), yylloc));
delete $2;
}
| '~' aexpression
{
$$ = new Value(make_shared<AExpression>(AENegate, static_cast<AExpression::Ptr>(*$2), yylloc));
delete $2;
}
| '[' array_items ']'
{
$$ = new Value(make_shared<AExpression>(AEArray, AValue(ATSimple, Array::Ptr($2)), yylloc));
}
| '(' aexpression ')'
{
$$ = $2;
@ -688,8 +665,7 @@ aexpression: simplevalue
}
;
value: simplevalue
| expressionlist
value: expressionlist
{
ExpressionList::Ptr exprl = ExpressionList::Ptr($1);
$$ = new Value(exprl);

View File

@ -18,7 +18,7 @@
add_library(methods SHARED
icingachecktask.cpp nullchecktask.cpp nulleventtask.cpp
pluginchecktask.cpp plugineventtask.cpp pluginnotificationtask.cpp
randomchecktask.cpp timeperiodtask.cpp
randomchecktask.cpp timeperiodtask.cpp utilityfuncs.cpp
)
target_link_libraries(methods ${Boost_LIBRARIES} base config icinga)

View File

@ -0,0 +1,35 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-present Icinga Development Team (http://www.icinga.org) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#include "methods/utilityfuncs.h"
#include "base/scriptfunction.h"
#include "base/utility.h"
#include <boost/regex.hpp>
using namespace icinga;
REGISTER_SCRIPTFUNCTION(regex, &UtilityFuncs::Regex);
REGISTER_SCRIPTFUNCTION(match, &Utility::Match);
bool UtilityFuncs::Regex(const String& pattern, const String& text)
{
boost::regex expr(pattern.GetData());
boost::smatch what;
return boost::regex_search(text.GetData(), what, expr);
}

View File

@ -0,0 +1,43 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-present Icinga Development Team (http://www.icinga.org) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#ifndef UTILITYFUNCS_H
#define UTILITYFUNCS_H
#include "methods/i2-methods.h"
#include "base/qstring.h"
namespace icinga
{
/**
* @ingroup methods
*/
class I2_METHODS_API UtilityFuncs
{
public:
static bool Regex(const String& pattern, const String& text);
private:
UtilityFuncs(void);
};
}
#endif /* UTILITYFUNCS_H */