Repository: nifi-minifi-cpp
Updated Branches:
  refs/heads/master b26b06479 -> eb9128c37


MINIFICPP-471 Implemented string manipulation EL functions

This closes #312.

Signed-off-by: Aldrin Piri <[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/eb9128c3
Tree: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/tree/eb9128c3
Diff: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/diff/eb9128c3

Branch: refs/heads/master
Commit: eb9128c37b2819da56785c3c5b453f33d5b2d085
Parents: b26b064
Author: Andrew I. Christianson <[email protected]>
Authored: Wed Apr 25 11:47:26 2018 -0400
Committer: Aldrin Piri <[email protected]>
Committed: Fri May 4 09:06:01 2018 -0400

----------------------------------------------------------------------
 EXPRESSIONS.md                                  | 76 ++++++++++++++++++--
 extensions/expression-language/Expression.cpp   | 29 ++++++++
 .../ExpressionLanguageTests.cpp                 | 32 +++++++++
 3 files changed, 133 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/eb9128c3/EXPRESSIONS.md
----------------------------------------------------------------------
diff --git a/EXPRESSIONS.md b/EXPRESSIONS.md
index f2a4876..95864d7 100644
--- a/EXPRESSIONS.md
+++ b/EXPRESSIONS.md
@@ -177,6 +177,10 @@ token, filename.
 - [`replaceAll`](#replaceall)
 - [`replaceNull`](#replacenull)
 - [`replaceEmpty`](#replaceempty)
+- [`trim`](#trim)
+- [`append`](#append)
+- [`prepend`](#prepend)
+- [`length`](#length)
 
 ### Mathematical Operations and Numeric Manipulation
 
@@ -222,11 +226,7 @@ token, filename.
 
 ### String Manipulation
 
-- `trim`
 - `getDelimitedField`
-- `append`
-- `prepend`
-- `length`
 
 ### Searching
 
@@ -859,6 +859,74 @@ filename.txt` and the attribute `hello` has the value ` `, 
then the Expression
 `${filename:replaceEmpty('abc')}` will return `a brand new filename.txt`, while
 `${hello:replaceEmpty('abc')}` will return `abc`.
 
+### trim
+
+**Description**: The `trim` function will remove any leading or trailing white
+space from its subject.
+
+**Subject Type**: String
+
+**Arguments**: No Arguments
+
+**Return Type**: String
+
+**Examples**: If the attribute `attr` has the value " 1 2 3 ", then the
+Expression `${attr:trim()}` will return the value "1 2 3".
+
+### append
+
+**Description**: The `append` function returns the result of appending the
+argument to the value of the Subject. If the Subject is null, returns the
+argument itself.
+
+**Subject Type**: String
+
+**Arguments**:
+
+| Argument | Description |
+| - | - |
+| value | The String to append to the end of the Subject |
+
+**Return Type**: String
+
+**Examples**: If the "filename" attribute has the value "a brand new
+filename.txt", then the Expression `${filename:append('.gz')}` will return "a
+brand new filename.txt.gz".
+
+### prepend
+
+**Description**: The `prepend` function returns the result of prepending the
+argument to the value of the Subject. If the subject is null, returns the
+argument itself.
+
+**Subject Type**: String
+
+**Arguments**:
+
+| Argument | Description |
+| - | - |
+| value | The String to prepend to the beginning of the Subject |
+
+**Return Type**: String
+
+**Examples**: If the "filename" attribute has the value "filename.txt", then
+the Expression `${filename:prepend('a brand new ')}` will return "a brand new
+filename.txt".
+
+### length
+
+**Description**: Returns the length of the Subject
+
+**Subject Type**: String
+
+**Arguments**: No arguments
+
+**Return Type**: String
+
+**Examples**: If the attribute "filename" has a value of "a brand new
+filename.txt" and the attribute "hello" does not exist, then the Expression
+`${filename:length()}` will return 24. `${hello:length()}` will return 0.
+
 ## Mathematical Operations and Numeric Manipulation
 
 For those functions that support Decimal and Number (whole number) types, the

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/eb9128c3/extensions/expression-language/Expression.cpp
----------------------------------------------------------------------
diff --git a/extensions/expression-language/Expression.cpp 
b/extensions/expression-language/Expression.cpp
index 9722028..6c2acc8 100644
--- a/extensions/expression-language/Expression.cpp
+++ b/extensions/expression-language/Expression.cpp
@@ -1288,6 +1288,27 @@ Value expr_find(const std::vector<Value> &args) {
 
 #endif  // EXPRESSION_LANGUAGE_USE_REGEX
 
+Value expr_trim(const std::vector<Value> &args) {
+  std::string result = args[0].asString();
+  auto ws_front = std::find_if_not(result.begin(), result.end(), [](int c) { 
return std::isspace(c); });
+  auto ws_back = std::find_if_not(result.rbegin(), result.rend(), [](int c) { 
return std::isspace(c); }).base();
+  return (ws_back <= ws_front ? Value(std::string()) : 
Value(std::string(ws_front, ws_back)));
+}
+
+Value expr_append(const std::vector<Value> &args) {
+  std::string result = args[0].asString();
+  return Value(result.append(args[1].asString()));
+}
+
+Value expr_prepend(const std::vector<Value> &args) {
+  std::string result = args[1].asString();
+  return Value(result.append(args[0].asString()));
+}
+
+Value expr_length(const std::vector<Value> &args) {
+  return Value(args[0].asString().length());
+}
+
 Value expr_binary_op(const std::vector<Value> &args,
                      long double (*ldop)(long double, long double),
                      int64_t (*iop)(int64_t, int64_t),
@@ -1594,6 +1615,14 @@ Expression make_dynamic_function(const std::string 
&function_name,
   } else if (function_name == "find") {
     return make_dynamic_function_incomplete<expr_find>(function_name, args, 1);
 #endif  // EXPRESSION_LANGUAGE_USE_REGEX
+  } else if (function_name == "trim") {
+    return make_dynamic_function_incomplete<expr_trim>(function_name, args, 0);
+  } else if (function_name == "append") {
+    return make_dynamic_function_incomplete<expr_append>(function_name, args, 
1);
+  } else if (function_name == "prepend") {
+    return make_dynamic_function_incomplete<expr_prepend>(function_name, args, 
1);
+  } else if (function_name == "length") {
+    return make_dynamic_function_incomplete<expr_length>(function_name, args, 
0);
   } else if (function_name == "plus") {
     return make_dynamic_function_incomplete<expr_plus>(function_name, args, 1);
   } else if (function_name == "minus") {

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/eb9128c3/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 5b687d7..17fb903 100644
--- a/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
+++ b/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
@@ -1189,3 +1189,35 @@ TEST_CASE("UUID", "[expressionUuid]") {  // NOLINT
   auto flow_file_a = std::make_shared<MockFlowFile>();
   REQUIRE(36 == expr({flow_file_a}).asString().length());
 }
+
+TEST_CASE("Trim", "[expressionTrim]") {  // NOLINT
+  auto expr = expression::compile("${message:trim()}");
+
+  auto flow_file_a = std::make_shared<MockFlowFile>();
+  flow_file_a->addAttribute("message", " 1 2 3 ");
+  REQUIRE("1 2 3" == expr({flow_file_a}).asString());
+}
+
+TEST_CASE("Append", "[expressionAppend]") {  // NOLINT
+  auto expr = expression::compile("${message:append('.gz')}");
+
+  auto flow_file_a = std::make_shared<MockFlowFile>();
+  flow_file_a->addAttribute("message", "a brand new filename.txt");
+  REQUIRE("a brand new filename.txt.gz" == expr({flow_file_a}).asString());
+}
+
+TEST_CASE("Prepend", "[expressionPrepend]") {  // NOLINT
+  auto expr = expression::compile("${message:prepend('a brand new ')}");
+
+  auto flow_file_a = std::make_shared<MockFlowFile>();
+  flow_file_a->addAttribute("message", "filename.txt");
+  REQUIRE("a brand new filename.txt" == expr({flow_file_a}).asString());
+}
+
+TEST_CASE("Length", "[expressionLength]") {  // NOLINT
+  auto expr = expression::compile("${message:length()}");
+
+  auto flow_file_a = std::make_shared<MockFlowFile>();
+  flow_file_a->addAttribute("message", "a brand new filename.txt");
+  REQUIRE(24 == expr({flow_file_a}).asUnsignedLong());
+}

Reply via email to