Repository: nifi-minifi-cpp
Updated Branches:
  refs/heads/master acd8c5538 -> e272487d0


MINIFICPP-331 Implemented string replacement functions

This closes #226.

Signed-off-by: Marc Parisi <[email protected]>


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/e272487d
Tree: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/tree/e272487d
Diff: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/diff/e272487d

Branch: refs/heads/master
Commit: e272487d0e640ff2740f8429dd56bdbb34cc7f62
Parents: acd8c55
Author: Andy I. Christianson <[email protected]>
Authored: Thu Dec 21 12:46:36 2017 -0500
Committer: Marc Parisi <[email protected]>
Committed: Tue Jan 16 12:44:01 2018 -0500

----------------------------------------------------------------------
 extensions/expression-language/Expression.cpp   |  62 ++++++++++++
 .../impl/expression/Expression.h                |   7 ++
 .../ExpressionLanguageTests.cpp                 | 100 +++++++++++++++++++
 3 files changed, 169 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/e272487d/extensions/expression-language/Expression.cpp
----------------------------------------------------------------------
diff --git a/extensions/expression-language/Expression.cpp 
b/extensions/expression-language/Expression.cpp
index 806ff6a..2220434 100644
--- a/extensions/expression-language/Expression.cpp
+++ b/extensions/expression-language/Expression.cpp
@@ -19,6 +19,7 @@
 #include <iostream>
 
 #include <expression/Expression.h>
+#include <regex>
 #include "Driver.h"
 
 namespace org {
@@ -96,6 +97,55 @@ std::string expr_substringAfterLast(const 
std::vector<std::string> &args) {
   return args[0].substr(last_pos + args[1].length());
 }
 
+#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];
+
+  std::string::size_type match_pos = 0;
+  match_pos = result.find(find, match_pos);
+
+  while (match_pos != std::string::npos) {
+    result.replace(match_pos, find.size(), replace);
+    match_pos = result.find(find, match_pos + replace.size());
+  }
+
+  return 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);
+}
+
+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);
+}
+
+std::string expr_replaceNull(const std::vector<std::string> &args) {
+  if (args[0].empty()) {
+    return args[1];
+  } else {
+    return args[0];
+  }
+}
+
+std::string expr_replaceEmpty(const std::vector<std::string> &args) {
+  std::string result = args[0];
+  const std::regex find("^[ \n\r\t]*$");
+  const std::string replace = args[1];
+  return std::regex_replace(result, find, replace);
+}
+
+#endif  // EXPRESSION_LANGUAGE_USE_REGEX
+
 template<std::string T(const std::vector<std::string> &)>
 Expression make_dynamic_function_incomplete(const std::string &function_name,
                                             const std::vector<Expression> 
&args,
@@ -149,6 +199,18 @@ Expression make_dynamic_function(const std::string 
&function_name,
     return 
make_dynamic_function_incomplete<expr_substringAfter>(function_name, args, 2);
   } else if (function_name == "substringAfterLast") {
     return 
make_dynamic_function_incomplete<expr_substringAfterLast>(function_name, args, 
2);
+#ifdef EXPRESSION_LANGUAGE_USE_REGEX
+  } else if (function_name == "replace") {
+    return make_dynamic_function_incomplete<expr_replace>(function_name, args, 
2);
+  } else if (function_name == "replaceFirst") {
+    return make_dynamic_function_incomplete<expr_replaceFirst>(function_name, 
args, 2);
+  } else if (function_name == "replaceAll") {
+    return make_dynamic_function_incomplete<expr_replaceAll>(function_name, 
args, 2);
+  } else if (function_name == "replaceNull") {
+    return make_dynamic_function_incomplete<expr_replaceNull>(function_name, 
args, 1);
+  } else if (function_name == "replaceEmpty") {
+    return make_dynamic_function_incomplete<expr_replaceEmpty>(function_name, 
args, 1);
+#endif  // EXPRESSION_LANGUAGE_USE_REGEX
   } else {
     std::string msg("Unknown expression function: ");
     msg.append(function_name);

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/e272487d/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 492bc0b..e245370 100644
--- a/extensions/expression-language/impl/expression/Expression.h
+++ b/extensions/expression-language/impl/expression/Expression.h
@@ -18,6 +18,13 @@
 #ifndef NIFI_MINIFI_CPP_EXPRESSION_H
 #define NIFI_MINIFI_CPP_EXPRESSION_H
 
+#define EXPRESSION_LANGUAGE_USE_REGEX
+
+// Disable regex in EL for incompatible compilers
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 9)
+#undef EXPRESSION_LANGUAGE_USE_REGEX
+#endif
+
 #include <core/FlowFile.h>
 
 #include <string>

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/e272487d/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 0af816d..8660af5 100644
--- a/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
+++ b/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
@@ -304,3 +304,103 @@ TEST_CASE("Substring After No Args", 
"[expressionLanguageSubstringAfterNoArgs]")
   flow_file_a->addAttribute("attr", "__flow_a_attr_value_a__");
   REQUIRE_THROWS_WITH(expr({flow_file_a}), "Attempted to call incomplete 
function");
 }
+
+#ifdef EXPRESSION_LANGUAGE_USE_REGEX
+
+TEST_CASE("Replace", "[expressionLanguageReplace]") {  // NOLINT
+  auto expr = expression::compile("${attr:replace('.', '_')}");
+
+  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}));
+}
+
+TEST_CASE("Replace 2", "[expressionLanguageReplace2]") {  // NOLINT
+  auto expr = expression::compile("${attr:replace(' ', '.')}");
+
+  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}));
+}
+
+TEST_CASE("Replace First", "[expressionLanguageReplaceFirst]") {  // NOLINT
+  auto expr = expression::compile("${attr:replaceFirst('a', 'the')}");
+
+  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}));
+}
+
+TEST_CASE("Replace First Regex", "[expressionLanguageReplaceFirstRegex]") {  
// NOLINT
+  auto expr = expression::compile("${attr:replaceFirst('[br]', 'g')}");
+
+  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}));
+}
+
+TEST_CASE("Replace All", "[expressionLanguageReplaceAll]") {  // NOLINT
+  auto expr = expression::compile("${attr:replaceAll('\\..*', '')}");
+
+  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}));
+}
+
+TEST_CASE("Replace All 2", "[expressionLanguageReplaceAll2]") {  // NOLINT
+  auto expr = expression::compile("${attr:replaceAll('a brand (new)', '$1')}");
+
+  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}));
+}
+
+TEST_CASE("Replace All 3", "[expressionLanguageReplaceAll3]") {  // NOLINT
+  auto expr = expression::compile("${attr:replaceAll('XYZ', 'ZZZ')}");
+
+  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}));
+}
+
+TEST_CASE("Replace Null", "[expressionLanguageReplaceNull]") {  // NOLINT
+  auto expr = expression::compile("${attr:replaceNull('abc')}");
+
+  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}));
+}
+
+TEST_CASE("Replace Null 2", "[expressionLanguageReplaceNull2]") {  // NOLINT
+  auto expr = expression::compile("${attr:replaceNull('abc')}");
+
+  auto flow_file_a = std::make_shared<MockFlowFile>();
+  flow_file_a->addAttribute("attr2", "a brand new filename.txt");
+  REQUIRE("abc" == expr({flow_file_a}));
+}
+
+TEST_CASE("Replace Empty", "[expressionLanguageReplaceEmpty]") {  // NOLINT
+  auto expr = expression::compile("${attr:replaceEmpty('abc')}");
+
+  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}));
+}
+
+TEST_CASE("Replace Empty 2", "[expressionLanguageReplaceEmpty2]") {  // NOLINT
+  auto expr = expression::compile("${attr:replaceEmpty('abc')}");
+
+  auto flow_file_a = std::make_shared<MockFlowFile>();
+  flow_file_a->addAttribute("attr", "  \t  \r  \n  ");
+  REQUIRE("abc" == expr({flow_file_a}));
+}
+
+TEST_CASE("Replace Empty 3", "[expressionLanguageReplaceEmpty2]") {  // NOLINT
+  auto expr = expression::compile("${attr:replaceEmpty('abc')}");
+
+  auto flow_file_a = std::make_shared<MockFlowFile>();
+  flow_file_a->addAttribute("attr2", "test");
+  REQUIRE("abc" == expr({flow_file_a}));
+}
+
+#endif  // EXPRESSION_LANGUAGE_USE_REGEX

Reply via email to