Skip to content

Commit

Permalink
Implement support for arrays in custom variables
Browse files Browse the repository at this point in the history
fixes #6544
  • Loading branch information
gunnarbeutner committed Nov 2, 2014
1 parent 9844a2c commit 3a41fe2
Show file tree
Hide file tree
Showing 13 changed files with 369 additions and 178 deletions.
30 changes: 30 additions & 0 deletions lib/base/utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <ios>
#include <fstream>
#include <iostream>
Expand Down Expand Up @@ -772,6 +773,35 @@ String Utility::NaturalJoin(const std::vector<String>& tokens)
return result;
}

String Utility::Join(const Array::Ptr& tokens, char separator)
{
String result;
bool first = true;

ObjectLock olock(tokens);
BOOST_FOREACH(const Value& vtoken, tokens) {
String token = Convert::ToString(vtoken);
boost::algorithm::replace_all(token, "\\", "\\\\");

char sep_before[2], sep_after[3];
sep_before[0] = separator;
sep_before[1] = '\0';
sep_after[0] = '\\';
sep_after[1] = separator;
sep_after[2] = '\0';
boost::algorithm::replace_all(token, sep_before, sep_after);

if (first)
first = false;
else
result += String(1, separator);

result += token;
}

return result;
}

String Utility::FormatDuration(double duration)
{
std::vector<String> tokens;
Expand Down
2 changes: 2 additions & 0 deletions lib/base/utility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include "base/i2-base.hpp"
#include "base/string.hpp"
#include "base/array.hpp"
#include <typeinfo>
#include <boost/function.hpp>
#include <boost/thread/tss.hpp>
Expand Down Expand Up @@ -96,6 +97,7 @@ class I2_BASE_API Utility
static void QueueAsyncCallback(const boost::function<void (void)>& callback, SchedulerPolicy policy = DefaultScheduler);

static String NaturalJoin(const std::vector<String>& tokens);
static String Join(const Array::Ptr& tokens, char separator);

static String FormatDuration(double duration);
static String FormatDateTime(const char *format, double ts);
Expand Down
20 changes: 14 additions & 6 deletions lib/compat/statusdatawriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -516,14 +516,22 @@ void StatusDataWriter::DumpCustomAttributes(std::ostream& fp, const CustomVarObj

ObjectLock olock(vars);
BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
if (!kv.first.IsEmpty()) {
fp << "\t";
if (kv.first.IsEmpty())
continue;

if (!CompatUtility::IsLegacyAttribute(object, kv.first))
fp << "_";
String value;

fp << kv.first << "\t" << kv.second << "\n";
}
if (kv.second.IsObjectType<Array>())
value = Utility::Join(kv.second, ';');
else
value = kv.second;

fp << "\t";

if (!CompatUtility::IsLegacyAttribute(object, kv.first))
fp << "_";

fp << kv.first << "\t" << value << "\n";
}
}

Expand Down
22 changes: 17 additions & 5 deletions lib/config/applyrule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ ApplyRule::RuleMap ApplyRule::m_Rules;
ApplyRule::CallbackMap ApplyRule::m_Callbacks;

ApplyRule::ApplyRule(const String& targetType, const String& name, const Expression::Ptr& expression,
const Expression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope)
: m_TargetType(targetType), m_Name(name), m_Expression(expression), m_Filter(filter), m_DebugInfo(di), m_Scope(scope)
const Expression::Ptr& filter, const String& fvar, const Expression::Ptr& fterm,
const DebugInfo& di, const Dictionary::Ptr& scope)
: m_TargetType(targetType), m_Name(name), m_Expression(expression), m_Filter(filter), m_FVar(fvar),
m_FTerm(fterm), m_DebugInfo(di), m_Scope(scope)
{ }

String ApplyRule::GetTargetType(void) const
Expand All @@ -52,6 +54,16 @@ Expression::Ptr ApplyRule::GetFilter(void) const
return m_Filter;
}

String ApplyRule::GetFVar(void) const
{
return m_FVar;
}

Expression::Ptr ApplyRule::GetFTerm(void) const
{
return m_FTerm;
}

DebugInfo ApplyRule::GetDebugInfo(void) const
{
return m_DebugInfo;
Expand All @@ -63,10 +75,10 @@ Dictionary::Ptr ApplyRule::GetScope(void) const
}

void ApplyRule::AddRule(const String& sourceType, const String& targetType, const String& name,
const Expression::Ptr& expression, const Expression::Ptr& filter,
const DebugInfo& di, const Dictionary::Ptr& scope)
const Expression::Ptr& expression, const Expression::Ptr& filter, const String& fvar,
const Expression::Ptr& fterm, const DebugInfo& di, const Dictionary::Ptr& scope)
{
m_Rules[sourceType].push_back(ApplyRule(targetType, name, expression, filter, di, scope));
m_Rules[sourceType].push_back(ApplyRule(targetType, name, expression, filter, fvar, fterm, di, scope));
}

bool ApplyRule::EvaluateFilter(const Dictionary::Ptr& scope) const
Expand Down
9 changes: 7 additions & 2 deletions lib/config/applyrule.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ class I2_CONFIG_API ApplyRule
String GetName(void) const;
Expression::Ptr GetExpression(void) const;
Expression::Ptr GetFilter(void) const;
String GetFVar(void) const;
Expression::Ptr GetFTerm(void) const;
DebugInfo GetDebugInfo(void) const;
Dictionary::Ptr GetScope(void) const;

bool EvaluateFilter(const Dictionary::Ptr& scope) const;

static void AddRule(const String& sourceType, const String& targetType, const String& name, const Expression::Ptr& expression,
const Expression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope);
const Expression::Ptr& filter, const String& fvar, const Expression::Ptr& fterm, const DebugInfo& di, const Dictionary::Ptr& scope);
static void EvaluateRules(bool clear);

static void RegisterType(const String& sourceType, const std::vector<String>& targetTypes, const ApplyRule::Callback& callback);
Expand All @@ -61,14 +63,17 @@ class I2_CONFIG_API ApplyRule
String m_Name;
Expression::Ptr m_Expression;
Expression::Ptr m_Filter;
String m_FVar;
Expression::Ptr m_FTerm;
DebugInfo m_DebugInfo;
Dictionary::Ptr m_Scope;

static CallbackMap m_Callbacks;
static RuleMap m_Rules;

ApplyRule(const String& targetType, const String& name, const Expression::Ptr& expression,
const Expression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope);
const Expression::Ptr& filter, const String& fvar, const Expression::Ptr& fterm,
const DebugInfo& di, const Dictionary::Ptr& scope);
};

}
Expand Down
5 changes: 4 additions & 1 deletion lib/config/base-type.conf
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@
%attribute %dictionary "methods",

%attribute %dictionary "vars" {
%attribute %string "*"
%attribute %string "*",
%attribute %array "*" {
%attribute %string "*"
}
},
}

Expand Down
35 changes: 30 additions & 5 deletions lib/config/config_parser.yy
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ static std::stack<bool> m_ObjectAssign;
static std::stack<bool> m_SeenAssign;
static std::stack<Expression::Ptr> m_Assign;
static std::stack<Expression::Ptr> m_Ignore;
static std::stack<String> m_FVar;
static std::stack<Expression::Ptr> m_FTerm;

void ConfigCompiler::Compile(void)
{
Expand All @@ -231,6 +233,8 @@ void ConfigCompiler::Compile(void)
m_SeenAssign = std::stack<bool>();
m_Assign = std::stack<Expression::Ptr>();
m_Ignore = std::stack<Expression::Ptr>();
m_FVar = std::stack<String>();
m_FTerm = std::stack<Expression::Ptr>();

try {
yyparse(this);
Expand Down Expand Up @@ -836,23 +840,36 @@ target_type_specifier: /* empty */
}
;

apply_for_specifier: /* empty */
| T_FOR '(' identifier T_IN rterm ')'
{
m_FVar.top() = $3;
free($3);

m_FTerm.top() = *$5;
delete $5;
}
;

apply:
{
m_Apply.push(true);
m_SeenAssign.push(false);
m_Assign.push(make_shared<Expression>(&Expression::OpLiteral, false, DebugInfo()));
m_Ignore.push(make_shared<Expression>(&Expression::OpLiteral, false, DebugInfo()));
m_FVar.push("");
m_FTerm.push(Expression::Ptr());
}
T_APPLY identifier rterm target_type_specifier rterm
T_APPLY identifier rterm apply_for_specifier target_type_specifier rterm
{
m_Apply.pop();

String type = $3;
free($3);
Expression::Ptr aname = *$4;
delete $4;
String target = $5;
free($5);
String target = $6;
free($6);

if (!ApplyRule::IsValidSourceType(type))
BOOST_THROW_EXCEPTION(ConfigError("'apply' cannot be used with type '" + type + "'") << errinfo_debuginfo(DebugInfoRange(@2, @3)));
Expand All @@ -878,8 +895,8 @@ apply:
BOOST_THROW_EXCEPTION(ConfigError("'apply' target type '" + target + "' is invalid") << errinfo_debuginfo(DebugInfoRange(@2, @5)));
}

Expression::Ptr exprl = *$6;
delete $6;
Expression::Ptr exprl = *$7;
delete $7;

exprl->MakeInline();

Expand All @@ -895,11 +912,19 @@ apply:
Expression::Ptr filter = make_shared<Expression>(&Expression::OpLogicalAnd, m_Assign.top(), rex, DebugInfoRange(@2, @5));
m_Assign.pop();

String fvar = m_FVar.top();
m_FVar.pop();

Expression::Ptr fterm = m_FTerm.top();
m_FTerm.pop();

Array::Ptr args = make_shared<Array>();
args->Add(type);
args->Add(target);
args->Add(aname);
args->Add(filter);
args->Add(fvar);
args->Add(fterm);

$$ = new Value(make_shared<Expression>(&Expression::OpApply, args, exprl, DebugInfoRange(@2, @5)));
}
Expand Down
4 changes: 3 additions & 1 deletion lib/config/expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -551,10 +551,12 @@ Value Expression::OpApply(const Expression* expr, const Dictionary::Ptr& locals,
String target = left->Get(1);
Expression::Ptr aname = left->Get(2);
Expression::Ptr filter = left->Get(3);
String fvar = left->Get(4);
Expression::Ptr fterm = left->Get(5);

String name = aname->Evaluate(locals, dhint);

ApplyRule::AddRule(type, target, name, exprl, filter, expr->m_DebugInfo, locals);
ApplyRule::AddRule(type, target, name, exprl, filter, fvar, fterm, expr->m_DebugInfo, locals);

return Empty;
}
Expand Down

0 comments on commit 3a41fe2

Please sign in to comment.