This is an automated email from the ASF dual-hosted git repository.

phrocker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git


The following commit(s) were added to refs/heads/master by this push:
     new ca2a68d  MINIFICPP-910 - Extend StringUtils with string join capability
ca2a68d is described below

commit ca2a68d6ec53924351ae1262c09cb47f28c0579c
Author: Arpad Boda <[email protected]>
AuthorDate: Wed Jun 19 01:08:01 2019 +0200

    MINIFICPP-910 - Extend StringUtils with string join capability
    
    This closes #585.
    
    Signed-off-by: Marc Parisi <[email protected]>
---
 libminifi/include/utils/StringUtils.h    | 85 ++++++++++++++++++++++++++++++++
 libminifi/test/unit/StringUtilsTests.cpp | 19 +++++++
 2 files changed, 104 insertions(+)

diff --git a/libminifi/include/utils/StringUtils.h 
b/libminifi/include/utils/StringUtils.h
index daf3a20..326a048 100644
--- a/libminifi/include/utils/StringUtils.h
+++ b/libminifi/include/utils/StringUtils.h
@@ -47,6 +47,26 @@ namespace nifi {
 namespace minifi {
 namespace utils {
 
+namespace {
+  template<class Char>
+  struct string_traits;
+  template<>
+  struct string_traits<char>{
+    template<class T>
+    static std::string convert_to_string(T&& t){
+      return std::to_string(std::forward<T>(t));
+    }
+  };
+
+  template<>
+  struct string_traits<wchar_t>{
+    template<class T>
+    static std::wstring convert_to_string(T&& t){
+      return std::to_wstring(std::forward<T>(t));
+    }
+  };
+}
+
 /**
  * Stateless String utility class.
  *
@@ -262,6 +282,71 @@ class StringUtils {
     return result_string;
   }
 
+  /**
+ * Concatenates strings stored in an arbitrary container using the provided 
separator.
+ * @tparam TChar char type of the string (char or wchar_t)
+ * @tparam U arbitrary container which has string or wstring value type
+ * @param separator that is inserted between each elements. Type should match 
the type of strings in container.
+ * @param container that contains the strings to be concatenated
+ * @return the result string
+ */
+  template<class TChar, class U, typename std::enable_if<std::is_same<typename 
U::value_type, std::basic_string<TChar>>::value>::type* = nullptr>
+  static std::basic_string<TChar> join(const std::basic_string<TChar>& 
separator, const U& container) {
+    typedef typename U::const_iterator ITtype;
+    ITtype it = container.cbegin();
+    std::basic_stringstream<TChar> sstream;
+    while(it != container.cend()) {
+      sstream << (*it);
+      ++it;
+      if(it != container.cend()) {
+        sstream << separator;
+      }
+    }
+    return sstream.str();
+  };
+
+  /**
+   * Just a wrapper for the above function to be able to create separator from 
const char* or const wchar_t*
+   */
+  template<class TChar, class U, typename std::enable_if<std::is_same<typename 
U::value_type, std::basic_string<TChar>>::value>::type* = nullptr>
+  static std::basic_string<TChar> join(const TChar* separator, const U& 
container) {
+    return join(std::basic_string<TChar>(separator), container);
+  };
+
+
+  /**
+   * Concatenates string representation of integrals stored in an arbitrary 
container using the provided separator.
+   * @tparam TChar char type of the string (char or wchar_t)
+   * @tparam U arbitrary container which has any integral value type
+   * @param separator that is inserted between each elements. Type of this 
determines the result type. (wstring separator -> wstring)
+   * @param container that contains the integrals to be concatenated
+   * @return the result string
+   */
+  template<class TChar, class U, typename 
std::enable_if<std::is_integral<typename U::value_type>::value>::type* = 
nullptr,
+      typename std::enable_if<!std::is_same<U, 
std::basic_string<TChar>>::value>::type* = nullptr>
+  static std::basic_string<TChar> join(const std::basic_string<TChar>& 
separator, const U& container) {
+    typedef typename U::const_iterator ITtype;
+    ITtype it = container.cbegin();
+    std::basic_stringstream<TChar> sstream;
+    while(it != container.cend()) {
+      sstream << string_traits<TChar>::convert_to_string(*it);
+      ++it;
+      if(it != container.cend()) {
+        sstream << separator;
+      }
+    }
+    return sstream.str();
+  }
+
+  /**
+   * Just a wrapper for the above function to be able to create separator from 
const char* or const wchar_t*
+   */
+  template<class TChar, class U, typename 
std::enable_if<std::is_integral<typename U::value_type>::value>::type* = 
nullptr,
+      typename std::enable_if<!std::is_same<U, 
std::basic_string<TChar>>::value>::type* = nullptr>
+  static std::basic_string<TChar> join(const TChar* separator, const U& 
container) {
+    return join(std::basic_string<TChar>(separator), container);
+  };
+
 };
 
 } /* namespace utils */
diff --git a/libminifi/test/unit/StringUtilsTests.cpp 
b/libminifi/test/unit/StringUtilsTests.cpp
index 3abf339..6486f29 100644
--- a/libminifi/test/unit/StringUtilsTests.cpp
+++ b/libminifi/test/unit/StringUtilsTests.cpp
@@ -17,6 +17,7 @@
  */
 
 #include <string>
+#include <list>
 #include <vector>
 #include <cstdlib>
 #include "../TestBase.h"
@@ -93,3 +94,21 @@ TEST_CASE("TestStringUtils::testEnv5", "[test split 
classname]") {
 
   REQUIRE(expected == StringUtils::replaceEnvironmentVariables(test_string));
 }
+
+TEST_CASE("TestStringUtils::testJoin", "[test string join]") {
+  std::set<std::string> strings = {"3", "2", "1"};
+  REQUIRE(StringUtils::join(",", strings) == "1,2,3");
+
+  std::wstring sep = L"é";
+  std::vector<std::wstring> wstrings = {L"1", L"2"};
+  REQUIRE(StringUtils::join(sep, wstrings) == L"1é2");
+
+  std::list<uint64_t> ulist = {1, 2};
+  REQUIRE(StringUtils::join(sep, ulist) == L"1é2");
+
+  REQUIRE(StringUtils::join(">", ulist) == "1>2");
+
+  REQUIRE(StringUtils::join("", ulist) == "12");
+
+  REQUIRE(StringUtils::join("this separator wont appear", 
std::vector<std::string>()) == "");
+}

Reply via email to