You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ph...@apache.org on 2018/03/14 17:34:37 UTC
nifi-minifi-cpp git commit: MINIFICPP-422 Refactored type system in
EL to preserve type information between operations
Repository: nifi-minifi-cpp
Updated Branches:
refs/heads/master 4232ac8b6 -> c4ea662c7
MINIFICPP-422 Refactored type system in EL to preserve type information between operations
This closes #274.
Signed-off-by: Marc Parisi <ph...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/commit/c4ea662c
Tree: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/tree/c4ea662c
Diff: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/diff/c4ea662c
Branch: refs/heads/master
Commit: c4ea662c76cde92a82c09aa0cd12a75b0bb595cc
Parents: 4232ac8
Author: Andrew I. Christianson <an...@andyic.org>
Authored: Fri Mar 9 12:56:37 2018 -0500
Committer: Marc Parisi <ph...@apache.org>
Committed: Wed Mar 14 13:34:22 2018 -0400
----------------------------------------------------------------------
CMakeLists.txt | 1 +
extensions/expression-language/CMakeLists.txt | 1 +
extensions/expression-language/Driver.h | 2 +-
extensions/expression-language/Expression.cpp | 323 +++++++++----------
.../expression-language/ProcessContextExpr.cpp | 4 +-
extensions/expression-language/common/Value.h | 238 ++++++++++++++
.../impl/expression/Expression.h | 23 +-
.../noop/expression/Expression.h | 1 +
.../ExpressionLanguageTests.cpp | 154 ++++-----
9 files changed, 486 insertions(+), 261 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c4ea662c/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d4245d5..166fd16 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -110,6 +110,7 @@ include_directories(thirdparty/rapidjson-1.1.0/include)
## Expression language extensions
option(DISABLE_EXPRESSION_LANGUAGE "Disables the scripting extensions." OFF)
+include_directories("extensions/expression-language/common")
if (DISABLE_EXPRESSION_LANGUAGE)
# Build expression language NoOp implementation, if necessary
include_directories("extensions/expression-language/noop")
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c4ea662c/extensions/expression-language/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/extensions/expression-language/CMakeLists.txt b/extensions/expression-language/CMakeLists.txt
index 53c87e6..b242d9a 100644
--- a/extensions/expression-language/CMakeLists.txt
+++ b/extensions/expression-language/CMakeLists.txt
@@ -39,6 +39,7 @@ flex_target(
add_flex_bison_dependency(el-scanner el-parser)
include_directories(../../libminifi/include ../../libminifi/include/core ../../thirdparty/spdlog-20170710/include ../../thirdparty/concurrentqueue ../../thirdparty/yaml-cpp-yaml-cpp-0.5.3/include ${CIVET_THIRDPARTY_ROOT}/include ../../thirdparty/)
+include_directories(common)
include_directories(impl)
file(GLOB SOURCES "*.cpp")
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c4ea662c/extensions/expression-language/Driver.h
----------------------------------------------------------------------
diff --git a/extensions/expression-language/Driver.h b/extensions/expression-language/Driver.h
index 4e66b4c..71dbbe4 100644
--- a/extensions/expression-language/Driver.h
+++ b/extensions/expression-language/Driver.h
@@ -41,7 +41,7 @@ class Driver : public yyFlexLexer {
public:
explicit Driver(std::istream *input = nullptr, std::ostream *output = nullptr)
: yyFlexLexer(input, output),
- result("") {
+ result(Value()) {
}
~Driver() override = default;
int lex(Parser::semantic_type *yylval,
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c4ea662c/extensions/expression-language/Expression.cpp
----------------------------------------------------------------------
diff --git a/extensions/expression-language/Expression.cpp b/extensions/expression-language/Expression.cpp
index d0c060a..4824f2d 100644
--- a/extensions/expression-language/Expression.cpp
+++ b/extensions/expression-language/Expression.cpp
@@ -39,138 +39,143 @@ Expression compile(const std::string &expr_str) {
}
Expression make_static(std::string val) {
- return Expression(std::move(val));
+ return Expression(Value(val));
}
-Expression make_dynamic(std::function<std::string(const Parameters ¶ms)> val_fn) {
- return Expression("", std::move(val_fn));
+Expression make_dynamic(const std::function<Value(const Parameters ¶ms)> &val_fn) {
+ return Expression(Value(), std::move(val_fn));
}
Expression make_dynamic_attr(const std::string &attribute_id) {
- return make_dynamic([attribute_id](const Parameters ¶ms) -> std::string {
+ return make_dynamic([attribute_id](const Parameters ¶ms) -> Value {
std::string result;
- params.flow_file.lock()->getAttribute(attribute_id, result);
- return result;
+ if (params.flow_file.lock()->getAttribute(attribute_id, result)) {
+ return Value(result);
+ } else {
+ return Value();
+ }
});
}
-std::string expr_hostname(const std::vector<std::string> &args) {
+Value expr_hostname(const std::vector<Value> &args) {
char hostname[1024];
hostname[1023] = '\0';
gethostname(hostname, 1023);
- return std::string(hostname);
+ return Value(std::string(hostname));
}
-std::string expr_toUpper(const std::vector<std::string> &args) {
- std::string result = args[0];
+Value expr_toUpper(const std::vector<Value> &args) {
+ std::string result = args[0].asString();
std::transform(result.begin(), result.end(), result.begin(), ::toupper);
- return result;
+ return Value(result);
}
-std::string expr_toLower(const std::vector<std::string> &args) {
- std::string result = args[0];
+Value expr_toLower(const std::vector<Value> &args) {
+ std::string result = args[0].asString();
std::transform(result.begin(), result.end(), result.begin(), ::tolower);
- return result;
+ return Value(result);
}
-std::string expr_substring(const std::vector<std::string> &args) {
+Value expr_substring(const std::vector<Value> &args) {
if (args.size() < 3) {
- return args[0].substr(std::stoul(args[1]));
+ return Value(args[0].asString().substr(args[1].asUnsignedLong()));
} else {
- return args[0].substr(std::stoul(args[1]), std::stoul(args[2]));
+ return Value(args[0].asString().substr(args[1].asUnsignedLong(), args[2].asUnsignedLong()));
}
}
-std::string expr_substringBefore(const std::vector<std::string> &args) {
- return args[0].substr(0, args[0].find(args[1]));
+Value expr_substringBefore(const std::vector<Value> &args) {
+ const std::string &arg_0 = args[0].asString();
+ return Value(arg_0.substr(0, arg_0.find(args[1].asString())));
}
-std::string expr_substringBeforeLast(const std::vector<std::string> &args) {
+Value expr_substringBeforeLast(const std::vector<Value> &args) {
size_t last_pos = 0;
- while (args[0].find(args[1], last_pos + 1) != std::string::npos) {
- last_pos = args[0].find(args[1], last_pos + 1);
+ const std::string &arg_0 = args[0].asString();
+ const std::string &arg_1 = args[1].asString();
+ while (arg_0.find(arg_1, last_pos + 1) != std::string::npos) {
+ last_pos = arg_0.find(arg_1, last_pos + 1);
}
- return args[0].substr(0, last_pos);
+ return Value(arg_0.substr(0, last_pos));
}
-std::string expr_substringAfter(const std::vector<std::string> &args) {
- return args[0].substr(args[0].find(args[1]) + args[1].length());
+Value expr_substringAfter(const std::vector<Value> &args) {
+ const std::string &arg_0 = args[0].asString();
+ const std::string &arg_1 = args[1].asString();
+ return Value(arg_0.substr(arg_0.find(arg_1) + arg_1.length()));
}
-std::string expr_substringAfterLast(const std::vector<std::string> &args) {
+Value expr_substringAfterLast(const std::vector<Value> &args) {
size_t last_pos = 0;
- while (args[0].find(args[1], last_pos + 1) != std::string::npos) {
- last_pos = args[0].find(args[1], last_pos + 1);
+ const std::string &arg_0 = args[0].asString();
+ const std::string &arg_1 = args[1].asString();
+ while (arg_0.find(arg_1, last_pos + 1) != std::string::npos) {
+ last_pos = arg_0.find(arg_1, last_pos + 1);
}
- return args[0].substr(last_pos + args[1].length());
+ return Value(arg_0.substr(last_pos + arg_1.length()));
}
-std::string expr_startsWith(const std::vector<std::string> &args) {
- if (args[0].substr(0, args[1].length()) == args[1]) {
- return "true";
- } else {
- return "false";
- }
+Value expr_startsWith(const std::vector<Value> &args) {
+ const std::string &arg_0 = args[0].asString();
+ const std::string &arg_1 = args[1].asString();
+ return Value(arg_0.substr(0, arg_1.length()) == arg_1);
}
-std::string expr_endsWith(const std::vector<std::string> &args) {
- if (args[0].substr(args[0].length() - args[1].length()) == args[1]) {
- return "true";
- } else {
- return "false";
- }
+Value expr_endsWith(const std::vector<Value> &args) {
+ const std::string &arg_0 = args[0].asString();
+ const std::string &arg_1 = args[1].asString();
+ return Value(arg_0.substr(arg_0.length() - arg_1.length()) == arg_1);
}
-std::string expr_contains(const std::vector<std::string> &args) {
- if (std::string::npos != args[0].find(args[1])) {
- return "true";
- } else {
- return "false";
- }
+Value expr_contains(const std::vector<Value> &args) {
+ return Value(std::string::npos != args[0].asString().find(args[1].asString()));
}
-std::string expr_in(const std::vector<std::string> &args) {
+Value expr_in(const std::vector<Value> &args) {
+ const std::string &arg_0 = args[0].asString();
for (int i = 1; i < args.size(); i++) {
- if (args[0] == args[i]) {
- return "true";
+ if (arg_0 == args[i].asString()) {
+ return Value(true);
}
}
- return "false";
+ return Value(false);
}
-std::string expr_indexOf(const std::vector<std::string> &args) {
- auto pos = args[0].find(args[1]);
+Value expr_indexOf(const std::vector<Value> &args) {
+ auto pos = args[0].asString().find(args[1].asString());
if (pos == std::string::npos) {
- return "-1";
+ return Value(static_cast<int64_t >(-1));
} else {
- return std::to_string(pos);
+ return Value(static_cast<int64_t >(pos));
}
}
-std::string expr_lastIndexOf(const std::vector<std::string> &args) {
+Value expr_lastIndexOf(const std::vector<Value> &args) {
size_t pos = std::string::npos;
- auto cur_pos = args[0].find(args[1], 0);
+ const std::string &arg_0 = args[0].asString();
+ const std::string &arg_1 = args[1].asString();
+ auto cur_pos = arg_0.find(arg_1, 0);
while (cur_pos != std::string::npos) {
pos = cur_pos;
- cur_pos = args[0].find(args[1], pos + 1);
+ cur_pos = arg_0.find(arg_1, pos + 1);
}
if (pos == std::string::npos) {
- return "-1";
+ return Value(static_cast<int64_t >(-1));
} else {
- return std::to_string(pos);
+ return Value(static_cast<int64_t >(pos));
}
}
#ifdef EXPRESSION_LANGUAGE_USE_REGEX
-std::string expr_replace(const std::vector<std::string> &args) {
- std::string result = args[0];
- const std::string find = args[1];
- const std::string replace = args[2];
+Value expr_replace(const std::vector<Value> &args) {
+ std::string result = args[0].asString();
+ const std::string &find = args[1].asString();
+ const std::string &replace = args[2].asString();
std::string::size_type match_pos = 0;
match_pos = result.find(find, match_pos);
@@ -180,126 +185,102 @@ std::string expr_replace(const std::vector<std::string> &args) {
match_pos = result.find(find, match_pos + replace.size());
}
- return result;
+ return Value(result);
}
-std::string expr_replaceFirst(const std::vector<std::string> &args) {
- std::string result = args[0];
- const std::regex find(args[1]);
- const std::string replace = args[2];
- return std::regex_replace(result, find, replace, std::regex_constants::format_first_only);
+Value expr_replaceFirst(const std::vector<Value> &args) {
+ std::string result = args[0].asString();
+ const std::regex find(args[1].asString());
+ const std::string &replace = args[2].asString();
+ return Value(std::regex_replace(result, find, replace, std::regex_constants::format_first_only));
}
-std::string expr_replaceAll(const std::vector<std::string> &args) {
- std::string result = args[0];
- const std::regex find(args[1]);
- const std::string replace = args[2];
- return std::regex_replace(result, find, replace);
+Value expr_replaceAll(const std::vector<Value> &args) {
+ std::string result = args[0].asString();
+ const std::regex find(args[1].asString());
+ const std::string &replace = args[2].asString();
+ return Value(std::regex_replace(result, find, replace));
}
-std::string expr_replaceNull(const std::vector<std::string> &args) {
- if (args[0].empty()) {
+Value expr_replaceNull(const std::vector<Value> &args) {
+ if (args[0].isNull()) {
return args[1];
} else {
return args[0];
}
}
-std::string expr_replaceEmpty(const std::vector<std::string> &args) {
- std::string result = args[0];
+Value expr_replaceEmpty(const std::vector<Value> &args) {
+ std::string result = args[0].asString();
const std::regex find("^[ \n\r\t]*$");
- const std::string replace = args[1];
- return std::regex_replace(result, find, replace);
+ const std::string &replace = args[1].asString();
+ return Value(std::regex_replace(result, find, replace));
}
-std::string expr_matches(const std::vector<std::string> &args) {
- const auto &subject = args[0];
- const std::regex expr = std::regex(args[1]);
+Value expr_matches(const std::vector<Value> &args) {
+ const auto &subject = args[0].asString();
+ const std::regex expr = std::regex(args[1].asString());
- if (std::regex_match(subject.begin(), subject.end(), expr)) {
- return "true";
- } else {
- return "false";
- }
+ return Value(std::regex_match(subject.begin(), subject.end(), expr));
}
-std::string expr_find(const std::vector<std::string> &args) {
- const auto &subject = args[0];
- const std::regex expr = std::regex(args[1]);
+Value expr_find(const std::vector<Value> &args) {
+ const auto &subject = args[0].asString();
+ const std::regex expr = std::regex(args[1].asString());
- if (std::regex_search(subject.begin(), subject.end(), expr)) {
- return "true";
- } else {
- return "false";
- }
+ return Value(std::regex_search(subject.begin(), subject.end(), expr));
}
#endif // EXPRESSION_LANGUAGE_USE_REGEX
-std::string expr_binaryOp(const std::vector<std::string> &args,
- long double (*ldop)(long double, long double),
- int (*iop)(int, int),
- bool long_only = false) {
+Value expr_binary_op(const std::vector<Value> &args,
+ long double (*ldop)(long double, long double),
+ int64_t (*iop)(int64_t, int64_t),
+ bool long_only = false) {
try {
- if (!long_only &&
- args[0].find('.') == args[0].npos &&
- args[1].find('.') == args[1].npos &&
- args[1].find('e') == args[1].npos &&
- args[0].find('e') == args[0].npos &&
- args[0].find('E') == args[0].npos &&
- args[1].find('E') == args[1].npos) {
- return std::to_string(iop(std::stoi(args[0]), std::stoi(args[1])));
+ if (!long_only && !args[0].isDecimal() && !args[1].isDecimal()) {
+ return Value(iop(args[0].asSignedLong(), args[1].asSignedLong()));
} else {
- std::stringstream ss;
- ss << std::fixed << std::setprecision(std::numeric_limits<double>::digits10)
- << ldop(std::stold(args[0]), std::stold(args[1]));
- auto result = ss.str();
- result.erase(result.find_last_not_of('0') + 1, std::string::npos);
-
- if (result.find('.') == result.length() - 1) {
- result.erase(result.length() - 1, std::string::npos);
- }
-
- return result;
+ return Value(ldop(args[0].asLongDouble(), args[1].asLongDouble()));
}
} catch (const std::exception &e) {
- return "";
+ return Value();
}
}
-std::string expr_plus(const std::vector<std::string> &args) {
- return expr_binaryOp(args,
- [](long double a, long double b) { return a + b; },
- [](int a, int b) { return a + b; });
+Value expr_plus(const std::vector<Value> &args) {
+ return expr_binary_op(args,
+ [](long double a, long double b) { return a + b; },
+ [](int64_t a, int64_t b) { return a + b; });
}
-std::string expr_minus(const std::vector<std::string> &args) {
- return expr_binaryOp(args,
- [](long double a, long double b) { return a - b; },
- [](int a, int b) { return a - b; });
+Value expr_minus(const std::vector<Value> &args) {
+ return expr_binary_op(args,
+ [](long double a, long double b) { return a - b; },
+ [](int64_t a, int64_t b) { return a - b; });
}
-std::string expr_multiply(const std::vector<std::string> &args) {
- return expr_binaryOp(args,
- [](long double a, long double b) { return a * b; },
- [](int a, int b) { return a * b; });
+Value expr_multiply(const std::vector<Value> &args) {
+ return expr_binary_op(args,
+ [](long double a, long double b) { return a * b; },
+ [](int64_t a, int64_t b) { return a * b; });
}
-std::string expr_divide(const std::vector<std::string> &args) {
- return expr_binaryOp(args,
- [](long double a, long double b) { return a / b; },
- [](int a, int b) { return a / b; },
- true);
+Value expr_divide(const std::vector<Value> &args) {
+ return expr_binary_op(args,
+ [](long double a, long double b) { return a / b; },
+ [](int64_t a, int64_t b) { return a / b; },
+ true);
}
-std::string expr_mod(const std::vector<std::string> &args) {
- return expr_binaryOp(args,
- [](long double a, long double b) { return std::fmod(a, b); },
- [](int a, int b) { return a % b; });
+Value expr_mod(const std::vector<Value> &args) {
+ return expr_binary_op(args,
+ [](long double a, long double b) { return std::fmod(a, b); },
+ [](int64_t a, int64_t b) { return a % b; });
}
-std::string expr_toRadix(const std::vector<std::string> &args) {
- int radix = std::stoi(args[1]);
+Value expr_toRadix(const std::vector<Value> &args) {
+ int64_t radix = args[1].asSignedLong();
if (radix < 2 || radix > 36) {
throw std::runtime_error("Cannot perform conversion due to invalid radix");
@@ -308,10 +289,11 @@ std::string expr_toRadix(const std::vector<std::string> &args) {
int pad_width = 0;
if (args.size() > 2) {
- pad_width = std::stoi(args[2]);
+ pad_width = static_cast<int>(args[2].asUnsignedLong());
}
- auto value = std::stoll(args[0], nullptr, 10);
+// auto value = std::stoll(args[0].asString(), nullptr, 10);
+ auto value = args[0].asSignedLong();
std::string sign;
@@ -334,27 +316,27 @@ std::string expr_toRadix(const std::vector<std::string> &args) {
std::stringstream ss;
ss << sign << std::setfill('0') << std::setw(pad_width) << str_num;
- return ss.str();
+ return Value(ss.str());
}
-std::string expr_fromRadix(const std::vector<std::string> &args) {
- int radix = std::stoi(args[1]);
+Value expr_fromRadix(const std::vector<Value> &args) {
+ auto radix = args[1].asSignedLong();
if (radix < 2 || radix > 36) {
throw std::runtime_error("Cannot perform conversion due to invalid radix");
}
- return std::to_string(std::stoll(args[0], nullptr, radix));
+ return Value(std::to_string(std::stoll(args[0].asString(), nullptr, radix)));
}
-std::string expr_random(const std::vector<std::string> &args) {
+Value expr_random(const std::vector<Value> &args) {
std::random_device random_device;
std::mt19937 generator(random_device());
- std::uniform_int_distribution<long long> distribution(0, LLONG_MAX);
- return std::to_string(distribution(generator));
+ std::uniform_int_distribution<int64_t> distribution(0, LLONG_MAX);
+ return Value(distribution(generator));
}
-template<std::string T(const std::vector<std::string> &)>
+template<Value T(const std::vector<Value> &)>
Expression make_dynamic_function_incomplete(const std::string &function_name,
const std::vector<Expression> &args,
std::size_t num_args) {
@@ -371,8 +353,8 @@ Expression make_dynamic_function_incomplete(const std::string &function_name,
throw std::runtime_error(message_ss.str());
}
- auto result = make_dynamic([=](const Parameters ¶ms) -> std::string {
- std::vector<std::string> evaluated_args;
+ auto result = make_dynamic([=](const Parameters ¶ms) -> Value {
+ std::vector<Value> evaluated_args;
for (const auto &arg : args) {
evaluated_args.emplace_back(arg(params));
@@ -384,7 +366,7 @@ Expression make_dynamic_function_incomplete(const std::string &function_name,
return result;
}
-std::string expr_literal(const std::vector<std::string> &args) {
+Value expr_literal(const std::vector<Value> &args) {
return args[0];
}
@@ -485,37 +467,34 @@ Expression Expression::operator+(const Expression &other_expr) const {
if (isDynamic() && other_expr.isDynamic()) {
auto val_fn = val_fn_;
auto other_val_fn = other_expr.val_fn_;
- return make_dynamic([val_fn, other_val_fn](const Parameters ¶ms) -> std::string {
- std::string result = val_fn(params);
- result.append(other_val_fn(params));
- return result;
+ return make_dynamic([val_fn, other_val_fn](const Parameters ¶ms) -> Value {
+ Value result = val_fn(params);
+ return Value(result.asString().append(other_val_fn(params).asString()));
});
} else if (isDynamic() && !other_expr.isDynamic()) {
auto val_fn = val_fn_;
auto other_val = other_expr.val_;
- return make_dynamic([val_fn, other_val](const Parameters ¶ms) -> std::string {
- std::string result = val_fn(params);
- result.append(other_val);
- return result;
+ return make_dynamic([val_fn, other_val](const Parameters ¶ms) -> Value {
+ Value result = val_fn(params);
+ return Value(result.asString().append(other_val.asString()));
});
} else if (!isDynamic() && other_expr.isDynamic()) {
auto val = val_;
auto other_val_fn = other_expr.val_fn_;
- return make_dynamic([val, other_val_fn](const Parameters ¶ms) -> std::string {
- std::string result(val);
- result.append(other_val_fn(params));
- return result;
+ return make_dynamic([val, other_val_fn](const Parameters ¶ms) -> Value {
+ Value result(val);
+ return Value(result.asString().append(other_val_fn(params).asString()));
});
} else if (!isDynamic() && !other_expr.isDynamic()) {
- std::string result(val_);
- result.append(other_expr.val_);
+ std::string result(val_.asString());
+ result.append(other_expr.val_.asString());
return make_static(result);
} else {
throw std::runtime_error("Invalid function composition");
}
}
-std::string Expression::operator()(const Parameters ¶ms) const {
+Value Expression::operator()(const Parameters ¶ms) const {
if (isDynamic()) {
return val_fn_(params);
} else {
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c4ea662c/extensions/expression-language/ProcessContextExpr.cpp
----------------------------------------------------------------------
diff --git a/extensions/expression-language/ProcessContextExpr.cpp b/extensions/expression-language/ProcessContextExpr.cpp
index c52b18c..68cdc54 100644
--- a/extensions/expression-language/ProcessContextExpr.cpp
+++ b/extensions/expression-language/ProcessContextExpr.cpp
@@ -32,7 +32,7 @@ bool ProcessContext::getProperty(const std::string &name, std::string &value,
expressions_.emplace(name, expression::compile(expression_str));
}
- value = expressions_[name]({flow_file});
+ value = expressions_[name]({flow_file}).asString();
return true;
}
@@ -45,7 +45,7 @@ bool ProcessContext::getDynamicProperty(const std::string &name, std::string &va
dynamic_property_expressions_.emplace(name, expression::compile(expression_str));
}
- value = dynamic_property_expressions_[name]({flow_file});
+ value = dynamic_property_expressions_[name]({flow_file}).asString();
return true;
}
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c4ea662c/extensions/expression-language/common/Value.h
----------------------------------------------------------------------
diff --git a/extensions/expression-language/common/Value.h b/extensions/expression-language/common/Value.h
new file mode 100644
index 0000000..75c80bc
--- /dev/null
+++ b/extensions/expression-language/common/Value.h
@@ -0,0 +1,238 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+#include <sstream>
+#include <iomanip>
+#include <limits>
+
+#ifndef NIFI_MINIFI_CPP_VALUE_H
+#define NIFI_MINIFI_CPP_VALUE_H
+
+namespace org {
+namespace apache {
+namespace nifi {
+namespace minifi {
+namespace expression {
+
+
+/**
+ * Represents an expression value, which can be one of multiple types or NULL
+ */
+class Value {
+ public:
+
+ /**
+ * Construct a default (NULL) value
+ */
+ Value() {
+ }
+
+ /**
+ * Construct a string value
+ */
+ explicit Value(const std::string &val) {
+ setString(val);
+ }
+
+ /**
+ * Construct a boolean value
+ */
+ explicit Value(bool val) {
+ setBoolean(val);
+ }
+
+ /**
+ * Construct an unsigned long value
+ */
+ explicit Value(uint64_t val) {
+ setUnsignedLong(val);
+ }
+
+ /**
+ * Construct a signed long value
+ */
+ explicit Value(int64_t val) {
+ setSignedLong(val);
+ }
+
+ /**
+ * Construct a long double value
+ */
+ explicit Value(long double val) {
+ setLongDouble(val);
+ }
+
+ bool isNull() const {
+ return is_null_;
+ };
+
+ bool isString() const {
+ return is_string_;
+ };
+
+ bool isDecimal() const {
+ if (is_long_double_) {
+ return true;
+ } else if (is_string_ && (string_val_.find('.') != string_val_.npos ||
+ string_val_.find('e') != string_val_.npos ||
+ string_val_.find('E') != string_val_.npos)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ void setSignedLong(int64_t val) {
+ is_null_ = false;
+ is_bool_ = false;
+ is_signed_long_ = true;
+ is_unsigned_long_ = false;
+ is_long_double_ = false;
+ is_string_ = false;
+ signed_long_val_ = val;
+ }
+
+ void setUnsignedLong(uint64_t val) {
+ is_null_ = false;
+ is_bool_ = false;
+ is_signed_long_ = false;
+ is_unsigned_long_ = true;
+ is_long_double_ = false;
+ is_string_ = false;
+ unsigned_long_val_ = val;
+ }
+
+ void setLongDouble(long double val) {
+ is_null_ = false;
+ is_bool_ = false;
+ is_signed_long_ = false;
+ is_unsigned_long_ = false;
+ is_long_double_ = true;
+ is_string_ = false;
+ long_double_val_ = val;
+ }
+
+ void setBoolean(bool val) {
+ is_null_ = false;
+ is_bool_ = true;
+ is_signed_long_ = false;
+ is_unsigned_long_ = false;
+ is_long_double_ = false;
+ is_string_ = false;
+ bool_val_ = val;
+ }
+
+ void setString(const std::string &val) {
+ is_null_ = false;
+ is_bool_ = false;
+ is_signed_long_ = false;
+ is_unsigned_long_ = false;
+ is_long_double_ = false;
+ is_string_ = true;
+ string_val_ = val;
+ }
+
+ std::string asString() const {
+ if (is_string_) {
+ return string_val_;
+ } else if (is_bool_) {
+ if (bool_val_) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (is_signed_long_) {
+ return std::to_string(signed_long_val_);
+ } else if (is_unsigned_long_) {
+ return std::to_string(unsigned_long_val_);
+ } else if (is_long_double_) {
+ std::stringstream ss;
+ ss << std::fixed << std::setprecision(std::numeric_limits<double>::digits10)
+ << long_double_val_;
+ auto result = ss.str();
+ result.erase(result.find_last_not_of('0') + 1, std::string::npos);
+
+ if (result.find('.') == result.length() - 1) {
+ result.erase(result.length() - 1, std::string::npos);
+ }
+
+ return result;
+ } else {
+ return "";
+ }
+ }
+
+ uint64_t asUnsignedLong() const {
+ if (is_unsigned_long_) {
+ return unsigned_long_val_;
+ } else if (is_string_) {
+ return std::stoul(string_val_);
+ } else {
+ return 0.0;
+ }
+ }
+
+ int64_t asSignedLong() const {
+ if (is_signed_long_) {
+ return signed_long_val_;
+ } else if (is_unsigned_long_) {
+ return unsigned_long_val_;
+ } else if (is_string_) {
+ return std::stoul(string_val_);
+ } else if (is_long_double_) {
+ return long_double_val_;
+ } else {
+ return 0.0;
+ }
+ }
+
+ long double asLongDouble() const {
+ if (is_signed_long_) {
+ return signed_long_val_;
+ } else if (is_unsigned_long_) {
+ return unsigned_long_val_;
+ } else if (is_long_double_) {
+ return long_double_val_;
+ } else if (is_string_) {
+ return std::stold(string_val_);
+ } else {
+ return 0.0;
+ }
+ }
+
+ private:
+ bool is_null_ = true;
+ bool is_string_ = false;
+ bool is_bool_ = false;
+ bool is_unsigned_long_ = false;
+ bool is_signed_long_ = false;
+ bool is_long_double_ = false;
+ bool bool_val_ = false;
+ uint64_t unsigned_long_val_ = 0;
+ int64_t signed_long_val_ = 0;
+ long double long_double_val_ = 0.0;
+ std::string string_val_ = "";
+};
+
+} /* namespace expression */
+} /* namespace minifi */
+} /* namespace nifi */
+} /* namespace apache */
+} /* namespace org */
+
+#endif //NIFI_MINIFI_CPP_VALUE_H
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c4ea662c/extensions/expression-language/impl/expression/Expression.h
----------------------------------------------------------------------
diff --git a/extensions/expression-language/impl/expression/Expression.h b/extensions/expression-language/impl/expression/Expression.h
index 9ee4a54..f123f77 100644
--- a/extensions/expression-language/impl/expression/Expression.h
+++ b/extensions/expression-language/impl/expression/Expression.h
@@ -25,6 +25,7 @@
#undef EXPRESSION_LANGUAGE_USE_REGEX
#endif
+#include <Value.h>
#include <core/FlowFile.h>
#include <string>
@@ -41,7 +42,7 @@ typedef struct {
std::weak_ptr<core::FlowFile> flow_file;
} Parameters;
-static const std::function<std::string(const Parameters ¶ms)> NOOP_FN;
+static const std::function<Value(const Parameters ¶ms)> NOOP_FN;
/**
* A NiFi expression language expression.
@@ -49,11 +50,15 @@ static const std::function<std::string(const Parameters ¶ms)> NOOP_FN;
class Expression {
public:
- explicit Expression(std::string val = "",
- std::function<std::string(const Parameters &)> val_fn = NOOP_FN)
- : val_(std::move(val)),
- val_fn_(std::move(val_fn)),
+ Expression() {
+ val_fn_ = NOOP_FN;
+ }
+
+ explicit Expression(Value val,
+ std::function<Value(const Parameters &)> val_fn = NOOP_FN)
+ : val_fn_(std::move(val_fn)),
fn_args_() {
+ val_ = val;
}
/**
@@ -80,11 +85,11 @@ class Expression {
* @param params
* @return dynamically-computed result of expression
*/
- std::string operator()(const Parameters ¶ms) const;
+ Value operator()(const Parameters ¶ms) const;
protected:
- std::string val_;
- std::function<std::string(const Parameters ¶ms)> val_fn_;
+ Value val_;
+ std::function<Value(const Parameters ¶ms)> val_fn_;
std::vector<Expression> fn_args_;
};
@@ -110,7 +115,7 @@ Expression make_static(std::string val);
* @param val_fn
* @return
*/
-Expression make_dynamic(std::function<std::string(const Parameters ¶ms)> val_fn);
+Expression make_dynamic(const std::function<Value(const Parameters ¶ms)> &val_fn);
/**
* Creates a dynamic expression which evaluates the given flow file attribute.
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c4ea662c/extensions/expression-language/noop/expression/Expression.h
----------------------------------------------------------------------
diff --git a/extensions/expression-language/noop/expression/Expression.h b/extensions/expression-language/noop/expression/Expression.h
index 08c4ae4..5cbebfe 100644
--- a/extensions/expression-language/noop/expression/Expression.h
+++ b/extensions/expression-language/noop/expression/Expression.h
@@ -19,6 +19,7 @@
#define NIFI_MINIFI_CPP_EXPRESSION_H
#include <core/FlowFile.h>
+#include <Value.h>
namespace org {
namespace apache {
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/c4ea662c/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp b/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
index da0d685..de3292e 100644
--- a/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
+++ b/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
@@ -32,24 +32,24 @@ class MockFlowFile : public core::FlowFile {
};
TEST_CASE("Trivial static expression", "[expressionLanguageTestTrivialStaticExpr]") { // NOLINT
- REQUIRE("a" == expression::make_static("a")({}));
+ REQUIRE("a" == expression::make_static("a")({}).asString());
}
TEST_CASE("Text expression", "[expressionLanguageTestTextExpression]") { // NOLINT
auto expr = expression::compile("text");
- REQUIRE("text" == expr({}));
+ REQUIRE("text" == expr({}).asString());
}
TEST_CASE("Text expression with escaped dollar", "[expressionLanguageTestEscapedDollar]") { // NOLINT
auto expr = expression::compile("te$$xt");
- REQUIRE("te$xt" == expr({}));
+ REQUIRE("te$xt" == expr({}).asString());
}
TEST_CASE("Attribute expression", "[expressionLanguageTestAttributeExpression]") { // NOLINT
auto flow_file = std::make_shared<MockFlowFile>();
flow_file->addAttribute("attr_a", "__attr_value_a__");
auto expr = expression::compile("text_before${attr_a}text_after");
- REQUIRE("text_before__attr_value_a__text_after" == expr({flow_file}));
+ REQUIRE("text_before__attr_value_a__text_after" == expr({flow_file}).asString());
}
TEST_CASE("Multi-attribute expression", "[expressionLanguageTestMultiAttributeExpression]") { // NOLINT
@@ -57,7 +57,7 @@ TEST_CASE("Multi-attribute expression", "[expressionLanguageTestMultiAttributeEx
flow_file->addAttribute("attr_a", "__attr_value_a__");
flow_file->addAttribute("attr_b", "__attr_value_b__");
auto expr = expression::compile("text_before${attr_a}text_between${attr_b}text_after");
- REQUIRE("text_before__attr_value_a__text_between__attr_value_b__text_after" == expr({flow_file}));
+ REQUIRE("text_before__attr_value_a__text_between__attr_value_b__text_after" == expr({flow_file}).asString());
}
TEST_CASE("Multi-flowfile attribute expression",
@@ -66,18 +66,18 @@ TEST_CASE("Multi-flowfile attribute expression",
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr_a", "__flow_a_attr_value_a__");
- REQUIRE("text_before__flow_a_attr_value_a__text_after" == expr({flow_file_a}));
+ REQUIRE("text_before__flow_a_attr_value_a__text_after" == expr({flow_file_a}).asString());
auto flow_file_b = std::make_shared<MockFlowFile>();
flow_file_b->addAttribute("attr_a", "__flow_b_attr_value_a__");
- REQUIRE("text_before__flow_b_attr_value_a__text_after" == expr({flow_file_b}));
+ REQUIRE("text_before__flow_b_attr_value_a__text_after" == expr({flow_file_b}).asString());
}
TEST_CASE("Attribute expression with whitespace", "[expressionLanguageTestAttributeExpressionWhitespace]") { // NOLINT
auto flow_file = std::make_shared<MockFlowFile>();
flow_file->addAttribute("attr_a", "__attr_value_a__");
auto expr = expression::compile("text_before${\n\tattr_a \r}text_after");
- REQUIRE("text_before__attr_value_a__text_after" == expr({flow_file}));
+ REQUIRE("text_before__attr_value_a__text_after" == expr({flow_file}).asString());
}
TEST_CASE("Special characters expression", "[expressionLanguageTestSpecialCharactersExpression]") { // NOLINT
@@ -85,7 +85,7 @@ TEST_CASE("Special characters expression", "[expressionLanguageTestSpecialCharac
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr_a", "__flow_a_attr_value_a__");
- REQUIRE("text_before|{}()[],:;\\/*#'\" \t\r\n__flow_a_attr_value_a__}()text_after" == expr({flow_file_a}));
+ REQUIRE("text_before|{}()[],:;\\/*#'\" \t\r\n__flow_a_attr_value_a__}()text_after" == expr({flow_file_a}).asString());
}
TEST_CASE("UTF-8 characters expression", "[expressionLanguageTestUTF8Expression]") { // NOLINT
@@ -93,7 +93,7 @@ TEST_CASE("UTF-8 characters expression", "[expressionLanguageTestUTF8Expression]
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr_a", "__flow_a_attr_value_a__");
- REQUIRE("text_before¥£€¢₡₢₣₤₥₦₧₨₩₪₫₭₮₯₹__flow_a_attr_value_a__text_after" == expr({flow_file_a}));
+ REQUIRE("text_before¥£€¢₡₢₣₤₥₦₧₨₩₪₫₭₮₯₹__flow_a_attr_value_a__text_after" == expr({flow_file_a}).asString());
}
TEST_CASE("UTF-8 characters attribute", "[expressionLanguageTestUTF8Attribute]") { // NOLINT
@@ -101,7 +101,7 @@ TEST_CASE("UTF-8 characters attribute", "[expressionLanguageTestUTF8Attribute]")
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr_a", "__¥£€¢₡₢₣₤₥₦₧₨₩₪₫₭₮₯₹__");
- REQUIRE("text_before__¥£€¢₡₢₣₤₥₦₧₨₩₪₫₭₮₯₹__text_after" == expr({flow_file_a}));
+ REQUIRE("text_before__¥£€¢₡₢₣₤₥₦₧₨₩₪₫₭₮₯₹__text_after" == expr({flow_file_a}).asString());
}
TEST_CASE("Single quoted attribute expression", "[expressionLanguageTestSingleQuotedAttributeExpression]") { // NOLINT
@@ -109,7 +109,7 @@ TEST_CASE("Single quoted attribute expression", "[expressionLanguageTestSingleQu
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("|{}()[],:;\\/*# \t\r\n$", "__flow_a_attr_value_a__");
- REQUIRE("text_before__flow_a_attr_value_a__text_after" == expr({flow_file_a}));
+ REQUIRE("text_before__flow_a_attr_value_a__text_after" == expr({flow_file_a}).asString());
}
TEST_CASE("Double quoted attribute expression", "[expressionLanguageTestDoubleQuotedAttributeExpression]") { // NOLINT
@@ -117,7 +117,7 @@ TEST_CASE("Double quoted attribute expression", "[expressionLanguageTestDoubleQu
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("|{}()[],:;\\/*# \t\r\n$", "__flow_a_attr_value_a__");
- REQUIRE("text_before__flow_a_attr_value_a__text_after" == expr({flow_file_a}));
+ REQUIRE("text_before__flow_a_attr_value_a__text_after" == expr({flow_file_a}).asString());
}
TEST_CASE("Hostname function", "[expressionLanguageTestHostnameFunction]") { // NOLINT
@@ -131,7 +131,7 @@ TEST_CASE("Hostname function", "[expressionLanguageTestHostnameFunction]") { //
expected.append("text_after");
auto flow_file_a = std::make_shared<MockFlowFile>();
- REQUIRE(expected == expr({flow_file_a}));
+ REQUIRE(expected == expr({flow_file_a}).asString());
}
TEST_CASE("ToUpper function", "[expressionLanguageTestToUpperFunction]") { // NOLINT
@@ -140,14 +140,14 @@ TEST_CASE("ToUpper function", "[expressionLanguageTestToUpperFunction]") { // N
}text_after)");
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr_a", "__flow_a_attr_value_a__");
- REQUIRE("text_before__FLOW_A_ATTR_VALUE_A__text_after" == expr({flow_file_a}));
+ REQUIRE("text_before__FLOW_A_ATTR_VALUE_A__text_after" == expr({flow_file_a}).asString());
}
TEST_CASE("ToUpper function w/o whitespace", "[expressionLanguageTestToUpperFunctionWithoutWhitespace]") { // NOLINT
auto expr = expression::compile(R"(text_before${attr_a:toUpper()}text_after)");
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr_a", "__flow_a_attr_value_a__");
- REQUIRE("text_before__FLOW_A_ATTR_VALUE_A__text_after" == expr({flow_file_a}));
+ REQUIRE("text_before__FLOW_A_ATTR_VALUE_A__text_after" == expr({flow_file_a}).asString());
}
TEST_CASE("ToLower function", "[expressionLanguageTestToLowerFunction]") { // NOLINT
@@ -156,7 +156,7 @@ TEST_CASE("ToLower function", "[expressionLanguageTestToLowerFunction]") { // N
}text_after)");
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr_a", "__FLOW_A_ATTR_VALUE_A__");
- REQUIRE("text_before__flow_a_attr_value_a__text_after" == expr({flow_file_a}));
+ REQUIRE("text_before__flow_a_attr_value_a__text_after" == expr({flow_file_a}).asString());
}
TEST_CASE("GetFile PutFile dynamic attribute", "[expressionLanguageTestGetFilePutFileDynamicAttribute]") { // NOLINT
@@ -257,7 +257,7 @@ TEST_CASE("Substring 2 arg", "[expressionLanguageSubstring2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "__flow_a_attr_value_a__");
- REQUIRE("text_before_a_attr_text_after" == expr({flow_file_a}));
+ REQUIRE("text_before_a_attr_text_after" == expr({flow_file_a}).asString());
}
TEST_CASE("Substring 1 arg", "[expressionLanguageSubstring1]") { // NOLINT
@@ -265,7 +265,7 @@ TEST_CASE("Substring 1 arg", "[expressionLanguageSubstring1]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "__flow_a_attr_value_a__");
- REQUIRE("text_before_a_attr_value_a__text_after" == expr({flow_file_a}));
+ REQUIRE("text_before_a_attr_value_a__text_after" == expr({flow_file_a}).asString());
}
TEST_CASE("Substring Before", "[expressionLanguageSubstringBefore]") { // NOLINT
@@ -273,7 +273,7 @@ TEST_CASE("Substring Before", "[expressionLanguageSubstringBefore]") { // NOLIN
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "__flow_a_attr_value_a__");
- REQUIRE("__flow_a_" == expr({flow_file_a}));
+ REQUIRE("__flow_a_" == expr({flow_file_a}).asString());
}
TEST_CASE("Substring Before Last", "[expressionLanguageSubstringBeforeLast]") { // NOLINT
@@ -281,7 +281,7 @@ TEST_CASE("Substring Before Last", "[expressionLanguageSubstringBeforeLast]") {
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "__flow_a_attr_value_a__");
- REQUIRE("__flow_a_attr_value" == expr({flow_file_a}));
+ REQUIRE("__flow_a_attr_value" == expr({flow_file_a}).asString());
}
TEST_CASE("Substring After", "[expressionLanguageSubstringAfter]") { // NOLINT
@@ -289,7 +289,7 @@ TEST_CASE("Substring After", "[expressionLanguageSubstringAfter]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "__flow_a_attr_value_a__");
- REQUIRE("_attr_value_a__" == expr({flow_file_a}));
+ REQUIRE("_attr_value_a__" == expr({flow_file_a}).asString());
}
TEST_CASE("Substring After Last", "[expressionLanguageSubstringAfterLast]") { // NOLINT
@@ -297,7 +297,7 @@ TEST_CASE("Substring After Last", "[expressionLanguageSubstringAfterLast]") { /
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "__flow_a_attr_value_a__");
- REQUIRE("__" == expr({flow_file_a}));
+ REQUIRE("__" == expr({flow_file_a}).asString());
}
TEST_CASE("Starts With", "[expressionLanguageStartsWith]") { // NOLINT
@@ -305,7 +305,7 @@ TEST_CASE("Starts With", "[expressionLanguageStartsWith]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "A BRAND TEST");
- REQUIRE("false" == expr({flow_file_a}));
+ REQUIRE("false" == expr({flow_file_a}).asString());
}
TEST_CASE("Starts With 2", "[expressionLanguageStartsWith2]") { // NOLINT
@@ -313,7 +313,7 @@ TEST_CASE("Starts With 2", "[expressionLanguageStartsWith2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand TEST");
- REQUIRE("true" == expr({flow_file_a}));
+ REQUIRE("true" == expr({flow_file_a}).asString());
}
TEST_CASE("Ends With", "[expressionLanguageEndsWith]") { // NOLINT
@@ -321,7 +321,7 @@ TEST_CASE("Ends With", "[expressionLanguageEndsWith]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.TXT");
- REQUIRE("false" == expr({flow_file_a}));
+ REQUIRE("false" == expr({flow_file_a}).asString());
}
TEST_CASE("Ends With 2", "[expressionLanguageEndsWith2]") { // NOLINT
@@ -329,7 +329,7 @@ TEST_CASE("Ends With 2", "[expressionLanguageEndsWith2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.TXT");
- REQUIRE("true" == expr({flow_file_a}));
+ REQUIRE("true" == expr({flow_file_a}).asString());
}
TEST_CASE("Contains", "[expressionLanguageContains]") { // NOLINT
@@ -337,7 +337,7 @@ TEST_CASE("Contains", "[expressionLanguageContains]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("true" == expr({flow_file_a}));
+ REQUIRE("true" == expr({flow_file_a}).asString());
}
TEST_CASE("Contains 2", "[expressionLanguageContains2]") { // NOLINT
@@ -345,7 +345,7 @@ TEST_CASE("Contains 2", "[expressionLanguageContains2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("false" == expr({flow_file_a}));
+ REQUIRE("false" == expr({flow_file_a}).asString());
}
TEST_CASE("In", "[expressionLanguageIn]") { // NOLINT
@@ -353,7 +353,7 @@ TEST_CASE("In", "[expressionLanguageIn]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "JOHN");
- REQUIRE("true" == expr({flow_file_a}));
+ REQUIRE("true" == expr({flow_file_a}).asString());
}
TEST_CASE("In 2", "[expressionLanguageIn2]") { // NOLINT
@@ -361,7 +361,7 @@ TEST_CASE("In 2", "[expressionLanguageIn2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "JOHN");
- REQUIRE("false" == expr({flow_file_a}));
+ REQUIRE("false" == expr({flow_file_a}).asString());
}
TEST_CASE("Substring Before No Args", "[expressionLanguageSubstringBeforeNoArgs]") { // NOLINT
@@ -381,7 +381,7 @@ TEST_CASE("Replace", "[expressionLanguageReplace]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("a brand new filename_txt" == expr({flow_file_a}));
+ REQUIRE("a brand new filename_txt" == expr({flow_file_a}).asString());
}
TEST_CASE("Replace 2", "[expressionLanguageReplace2]") { // NOLINT
@@ -389,7 +389,7 @@ TEST_CASE("Replace 2", "[expressionLanguageReplace2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("a.brand.new.filename.txt" == expr({flow_file_a}));
+ REQUIRE("a.brand.new.filename.txt" == expr({flow_file_a}).asString());
}
TEST_CASE("Replace First", "[expressionLanguageReplaceFirst]") { // NOLINT
@@ -397,7 +397,7 @@ TEST_CASE("Replace First", "[expressionLanguageReplaceFirst]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("the brand new filename.txt" == expr({flow_file_a}));
+ REQUIRE("the brand new filename.txt" == expr({flow_file_a}).asString());
}
TEST_CASE("Replace First Regex", "[expressionLanguageReplaceFirstRegex]") { // NOLINT
@@ -405,7 +405,7 @@ TEST_CASE("Replace First Regex", "[expressionLanguageReplaceFirstRegex]") { //
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("a grand new filename.txt" == expr({flow_file_a}));
+ REQUIRE("a grand new filename.txt" == expr({flow_file_a}).asString());
}
TEST_CASE("Replace All", "[expressionLanguageReplaceAll]") { // NOLINT
@@ -413,7 +413,7 @@ TEST_CASE("Replace All", "[expressionLanguageReplaceAll]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("a brand new filename" == expr({flow_file_a}));
+ REQUIRE("a brand new filename" == expr({flow_file_a}).asString());
}
TEST_CASE("Replace All 2", "[expressionLanguageReplaceAll2]") { // NOLINT
@@ -421,7 +421,7 @@ TEST_CASE("Replace All 2", "[expressionLanguageReplaceAll2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("new filename.txt" == expr({flow_file_a}));
+ REQUIRE("new filename.txt" == expr({flow_file_a}).asString());
}
TEST_CASE("Replace All 3", "[expressionLanguageReplaceAll3]") { // NOLINT
@@ -429,7 +429,7 @@ TEST_CASE("Replace All 3", "[expressionLanguageReplaceAll3]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("a brand new filename.txt" == expr({flow_file_a}));
+ REQUIRE("a brand new filename.txt" == expr({flow_file_a}).asString());
}
TEST_CASE("Replace Null", "[expressionLanguageReplaceNull]") { // NOLINT
@@ -437,7 +437,7 @@ TEST_CASE("Replace Null", "[expressionLanguageReplaceNull]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("a brand new filename.txt" == expr({flow_file_a}));
+ REQUIRE("a brand new filename.txt" == expr({flow_file_a}).asString());
}
TEST_CASE("Replace Null 2", "[expressionLanguageReplaceNull2]") { // NOLINT
@@ -445,7 +445,7 @@ TEST_CASE("Replace Null 2", "[expressionLanguageReplaceNull2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr2", "a brand new filename.txt");
- REQUIRE("abc" == expr({flow_file_a}));
+ REQUIRE("abc" == expr({flow_file_a}).asString());
}
TEST_CASE("Replace Empty", "[expressionLanguageReplaceEmpty]") { // NOLINT
@@ -453,7 +453,7 @@ TEST_CASE("Replace Empty", "[expressionLanguageReplaceEmpty]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("a brand new filename.txt" == expr({flow_file_a}));
+ REQUIRE("a brand new filename.txt" == expr({flow_file_a}).asString());
}
TEST_CASE("Replace Empty 2", "[expressionLanguageReplaceEmpty2]") { // NOLINT
@@ -461,7 +461,7 @@ TEST_CASE("Replace Empty 2", "[expressionLanguageReplaceEmpty2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", " \t \r \n ");
- REQUIRE("abc" == expr({flow_file_a}));
+ REQUIRE("abc" == expr({flow_file_a}).asString());
}
TEST_CASE("Replace Empty 3", "[expressionLanguageReplaceEmpty2]") { // NOLINT
@@ -469,7 +469,7 @@ TEST_CASE("Replace Empty 3", "[expressionLanguageReplaceEmpty2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr2", "test");
- REQUIRE("abc" == expr({flow_file_a}));
+ REQUIRE("abc" == expr({flow_file_a}).asString());
}
TEST_CASE("Matches", "[expressionLanguageMatches]") { // NOLINT
@@ -477,7 +477,7 @@ TEST_CASE("Matches", "[expressionLanguageMatches]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "At:est");
- REQUIRE("true" == expr({flow_file_a}));
+ REQUIRE("true" == expr({flow_file_a}).asString());
}
TEST_CASE("Matches 2", "[expressionLanguageMatches2]") { // NOLINT
@@ -485,7 +485,7 @@ TEST_CASE("Matches 2", "[expressionLanguageMatches2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "At:something");
- REQUIRE("false" == expr({flow_file_a}));
+ REQUIRE("false" == expr({flow_file_a}).asString());
}
TEST_CASE("Matches 3", "[expressionLanguageMatches3]") { // NOLINT
@@ -493,7 +493,7 @@ TEST_CASE("Matches 3", "[expressionLanguageMatches3]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", " At:est");
- REQUIRE("false" == expr({flow_file_a}));
+ REQUIRE("false" == expr({flow_file_a}).asString());
}
TEST_CASE("Find", "[expressionLanguageFind]") { // NOLINT
@@ -501,7 +501,7 @@ TEST_CASE("Find", "[expressionLanguageFind]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("true" == expr({flow_file_a}));
+ REQUIRE("true" == expr({flow_file_a}).asString());
}
TEST_CASE("Find 2", "[expressionLanguageFind2]") { // NOLINT
@@ -509,7 +509,7 @@ TEST_CASE("Find 2", "[expressionLanguageFind2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("false" == expr({flow_file_a}));
+ REQUIRE("false" == expr({flow_file_a}).asString());
}
TEST_CASE("Find 3", "[expressionLanguageFind3]") { // NOLINT
@@ -517,7 +517,7 @@ TEST_CASE("Find 3", "[expressionLanguageFind3]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("true" == expr({flow_file_a}));
+ REQUIRE("true" == expr({flow_file_a}).asString());
}
TEST_CASE("IndexOf", "[expressionLanguageIndexOf]") { // NOLINT
@@ -525,7 +525,7 @@ TEST_CASE("IndexOf", "[expressionLanguageIndexOf]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("-1" == expr({flow_file_a}));
+ REQUIRE("-1" == expr({flow_file_a}).asString());
}
TEST_CASE("IndexOf2", "[expressionLanguageIndexOf2]") { // NOLINT
@@ -533,7 +533,7 @@ TEST_CASE("IndexOf2", "[expressionLanguageIndexOf2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("20" == expr({flow_file_a}));
+ REQUIRE("20" == expr({flow_file_a}).asString());
}
TEST_CASE("IndexOf3", "[expressionLanguageIndexOf3]") { // NOLINT
@@ -541,7 +541,7 @@ TEST_CASE("IndexOf3", "[expressionLanguageIndexOf3]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("0" == expr({flow_file_a}));
+ REQUIRE("0" == expr({flow_file_a}).asString());
}
TEST_CASE("IndexOf4", "[expressionLanguageIndexOf4]") { // NOLINT
@@ -549,7 +549,7 @@ TEST_CASE("IndexOf4", "[expressionLanguageIndexOf4]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("1" == expr({flow_file_a}));
+ REQUIRE("1" == expr({flow_file_a}).asString());
}
TEST_CASE("LastIndexOf", "[expressionLanguageLastIndexOf]") { // NOLINT
@@ -557,7 +557,7 @@ TEST_CASE("LastIndexOf", "[expressionLanguageLastIndexOf]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("-1" == expr({flow_file_a}));
+ REQUIRE("-1" == expr({flow_file_a}).asString());
}
TEST_CASE("LastIndexOf2", "[expressionLanguageLastIndexOf2]") { // NOLINT
@@ -565,7 +565,7 @@ TEST_CASE("LastIndexOf2", "[expressionLanguageLastIndexOf2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("20" == expr({flow_file_a}));
+ REQUIRE("20" == expr({flow_file_a}).asString());
}
TEST_CASE("LastIndexOf3", "[expressionLanguageLastIndexOf3]") { // NOLINT
@@ -573,7 +573,7 @@ TEST_CASE("LastIndexOf3", "[expressionLanguageLastIndexOf3]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("17" == expr({flow_file_a}));
+ REQUIRE("17" == expr({flow_file_a}).asString());
}
TEST_CASE("LastIndexOf4", "[expressionLanguageLastIndexOf4]") { // NOLINT
@@ -581,7 +581,7 @@ TEST_CASE("LastIndexOf4", "[expressionLanguageLastIndexOf4]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "a brand new filename.txt");
- REQUIRE("11" == expr({flow_file_a}));
+ REQUIRE("11" == expr({flow_file_a}).asString());
}
#endif // EXPRESSION_LANGUAGE_USE_REGEX
@@ -591,7 +591,7 @@ TEST_CASE("Plus Integer", "[expressionLanguagePlusInteger]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "11");
- REQUIRE("24" == expr({flow_file_a}));
+ REQUIRE("24" == expr({flow_file_a}).asString());
}
TEST_CASE("Plus Decimal", "[expressionLanguagePlusDecimal]") { // NOLINT
@@ -599,7 +599,7 @@ TEST_CASE("Plus Decimal", "[expressionLanguagePlusDecimal]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "11.1");
- REQUIRE("-2.24567" == expr({flow_file_a}));
+ REQUIRE("-2.24567" == expr({flow_file_a}).asString());
}
TEST_CASE("Plus Exponent", "[expressionLanguagePlusExponent]") { // NOLINT
@@ -607,7 +607,7 @@ TEST_CASE("Plus Exponent", "[expressionLanguagePlusExponent]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "11");
- REQUIRE("10000011" == expr({flow_file_a}));
+ REQUIRE("10000011" == expr({flow_file_a}).asString());
}
TEST_CASE("Plus Exponent 2", "[expressionLanguagePlusExponent2]") { // NOLINT
@@ -615,7 +615,7 @@ TEST_CASE("Plus Exponent 2", "[expressionLanguagePlusExponent2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "11.345678901234");
- REQUIRE("10000011.345678901234351" == expr({flow_file_a}));
+ REQUIRE("10000011.345678901234351" == expr({flow_file_a}).asString());
}
TEST_CASE("Minus Integer", "[expressionLanguageMinusInteger]") { // NOLINT
@@ -623,7 +623,7 @@ TEST_CASE("Minus Integer", "[expressionLanguageMinusInteger]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "11");
- REQUIRE("-2" == expr({flow_file_a}));
+ REQUIRE("-2" == expr({flow_file_a}).asString());
}
TEST_CASE("Minus Decimal", "[expressionLanguageMinusDecimal]") { // NOLINT
@@ -631,7 +631,7 @@ TEST_CASE("Minus Decimal", "[expressionLanguageMinusDecimal]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "11.1");
- REQUIRE("24.44567" == expr({flow_file_a}));
+ REQUIRE("24.44567" == expr({flow_file_a}).asString());
}
TEST_CASE("Multiply Integer", "[expressionLanguageMultiplyInteger]") { // NOLINT
@@ -639,7 +639,7 @@ TEST_CASE("Multiply Integer", "[expressionLanguageMultiplyInteger]") { // NOLIN
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "11");
- REQUIRE("143" == expr({flow_file_a}));
+ REQUIRE("143" == expr({flow_file_a}).asString());
}
TEST_CASE("Multiply Decimal", "[expressionLanguageMultiplyDecimal]") { // NOLINT
@@ -647,7 +647,7 @@ TEST_CASE("Multiply Decimal", "[expressionLanguageMultiplyDecimal]") { // NOLIN
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "11.1");
- REQUIRE("-148.136937" == expr({flow_file_a}));
+ REQUIRE("-148.136937" == expr({flow_file_a}).asString());
}
TEST_CASE("Divide Integer", "[expressionLanguageDivideInteger]") { // NOLINT
@@ -655,7 +655,7 @@ TEST_CASE("Divide Integer", "[expressionLanguageDivideInteger]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "11");
- REQUIRE("0.846153846153846" == expr({flow_file_a}));
+ REQUIRE("0.846153846153846" == expr({flow_file_a}).asString());
}
TEST_CASE("Divide Decimal", "[expressionLanguageDivideDecimal]") { // NOLINT
@@ -663,7 +663,7 @@ TEST_CASE("Divide Decimal", "[expressionLanguageDivideDecimal]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "11.1");
- REQUIRE("-0.831730441409086" == expr({flow_file_a}));
+ REQUIRE("-0.831730441409086" == expr({flow_file_a}).asString());
}
TEST_CASE("To Radix", "[expressionLanguageToRadix]") { // NOLINT
@@ -671,7 +671,7 @@ TEST_CASE("To Radix", "[expressionLanguageToRadix]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "10");
- REQUIRE("0000000000001010" == expr({flow_file_a}));
+ REQUIRE("0000000000001010" == expr({flow_file_a}).asString());
}
TEST_CASE("To Radix 2", "[expressionLanguageToRadix2]") { // NOLINT
@@ -679,7 +679,7 @@ TEST_CASE("To Radix 2", "[expressionLanguageToRadix2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "13");
- REQUIRE("d" == expr({flow_file_a}));
+ REQUIRE("d" == expr({flow_file_a}).asString());
}
TEST_CASE("To Radix 3", "[expressionLanguageToRadix3]") { // NOLINT
@@ -687,7 +687,7 @@ TEST_CASE("To Radix 3", "[expressionLanguageToRadix3]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "-2347");
- REQUIRE("-000004a1" == expr({flow_file_a}));
+ REQUIRE("-000004a1" == expr({flow_file_a}).asString());
}
TEST_CASE("From Radix", "[expressionLanguageFromRadix]") { // NOLINT
@@ -695,7 +695,7 @@ TEST_CASE("From Radix", "[expressionLanguageFromRadix]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "0000000000001010");
- REQUIRE("10" == expr({flow_file_a}));
+ REQUIRE("10" == expr({flow_file_a}).asString());
}
TEST_CASE("From Radix 2", "[expressionLanguageFromRadix2]") { // NOLINT
@@ -703,7 +703,7 @@ TEST_CASE("From Radix 2", "[expressionLanguageFromRadix2]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "d");
- REQUIRE("13" == expr({flow_file_a}));
+ REQUIRE("13" == expr({flow_file_a}).asString());
}
TEST_CASE("From Radix 3", "[expressionLanguageFromRadix3]") { // NOLINT
@@ -711,14 +711,14 @@ TEST_CASE("From Radix 3", "[expressionLanguageFromRadix3]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "-000004a1");
- REQUIRE("-2347" == expr({flow_file_a}));
+ REQUIRE("-2347" == expr({flow_file_a}).asString());
}
TEST_CASE("Random", "[expressionLanguageRandom]") { // NOLINT
auto expr = expression::compile("${random()}");
auto flow_file_a = std::make_shared<MockFlowFile>();
- auto result = std::stoll(expr({flow_file_a}));
+ auto result = expr({flow_file_a}).asSignedLong();
REQUIRE(result > 0);
}
@@ -727,14 +727,14 @@ TEST_CASE("Chained call", "[expressionChainedCall]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "7");
- REQUIRE("22" == expr({flow_file_a}));
+ REQUIRE("22" == expr({flow_file_a}).asString());
}
TEST_CASE("Chained call 2", "[expressionChainedCall2]") { // NOLINT
auto expr = expression::compile("${literal(10):multiply(2):plus(1):multiply(2)}");
auto flow_file_a = std::make_shared<MockFlowFile>();
- REQUIRE("42" == expr({flow_file_a}));
+ REQUIRE(42 == expr({flow_file_a}).asSignedLong());
}
TEST_CASE("Chained call 3", "[expressionChainedCall3]") { // NOLINT
@@ -742,5 +742,5 @@ TEST_CASE("Chained call 3", "[expressionChainedCall3]") { // NOLINT
auto flow_file_a = std::make_shared<MockFlowFile>();
flow_file_a->addAttribute("attr", "7");
- REQUIRE("238" == expr({flow_file_a}));
+ REQUIRE("238" == expr({flow_file_a}).asString());
}