arpadboda commented on a change in pull request #585: MINIFICPP-910 - Extend 
StringUtils with string join capability
URL: https://github.com/apache/nifi-minifi-cpp/pull/585#discussion_r292937396
 
 

 ##########
 File path: libminifi/include/utils/StringUtils.h
 ##########
 @@ -92,172 +103,104 @@ class StringUtils {
    * @returns modified string
    */
 
-  static inline std::string trimRight(std::string s) {
-    s.erase(std::find_if(s.rbegin(), s.rend(), 
std::not1(std::pointer_to_unary_function<int, int>(isspace))).base(), s.end());
+  inline std::string trimRight(std::string s) {
+    s.erase(std::find_if(s.rbegin(), s.rend(), 
std::not1(std::pointer_to_unary_function<int, int>(std::isspace))).base(), 
s.end());
     return s;
   }
 
+  /**
+  * Trims a string left to right
+  * @param s incoming string
+  * @returns modified string
+  */
+  inline std::string trim(std::string s) {
+    return trimRight(trimLeft(s));
+  }
+
   /**
    * Compares strings by lower casing them.
    */
-  static inline bool equalsIgnoreCase(const std::string &left, const 
std::string right) {
+  inline bool equalsIgnoreCase(const std::string &left, const std::string 
right) {
     if (left.length() == right.length()) {
-      return std::equal(right.begin(), right.end(), left.begin(), [](unsigned 
char lc, unsigned char rc) {return tolower(lc) == tolower(rc);});
+      return std::equal(right.begin(), right.end(), left.begin(), [](unsigned 
char lc, unsigned char rc) {return std::tolower(lc) == std::tolower(rc);});
     } else {
       return false;
     }
   }
 
-  static std::vector<std::string> split(const std::string &str, const 
std::string &delimiter) {
-    std::vector<std::string> result;
-    auto curr = str.begin();
-    auto end = str.end();
-    auto is_func = [delimiter](int s) {
-      return delimiter.at(0) == s;
-    };
-    while (curr != end) {
-      curr = std::find_if_not(curr, end, is_func);
-      if (curr == end) {
-        break;
-      }
-      auto next = std::find_if(curr, end, is_func);
-      result.push_back(std::string(curr, next));
-      curr = next;
-    }
-
-    return result;
-  }
+  std::vector<std::string> split(const std::string &str, const std::string 
&delimiter);
 
   /**
    * Converts a string to a float
    * @param input input string
    * @param output output float
    * @param cp failure policy
    */
-  static bool StringToFloat(std::string input, float &output, FailurePolicy cp 
= RETURN) {
-    try {
-      output = std::stof(input);
-    } catch (const std::invalid_argument &ie) {
-      switch (cp) {
-        case RETURN:
-        case NOTHING:
-          return false;
-        case EXIT:
-          exit(1);
-        case EXCEPT:
-          throw ie;
-      }
-    } catch (const std::out_of_range &ofr) {
-      switch (cp) {
-        case RETURN:
-        case NOTHING:
-          return false;
-        case EXIT:
-          exit(1);
-        case EXCEPT:
-          throw ofr;
+  bool StringToFloat(std::string input, float &output, FailurePolicy cp = 
RETURN);
 
-      }
-    }
-
-    return true;
+  std::string& replaceAll(std::string& source_string, const std::string 
&from_string, const std::string &to_string);
 
-  }
-
-  static std::string replaceEnvironmentVariables(std::string& original_string) 
{
-    int32_t beg_seq = 0;
-    int32_t end_seq = 0;
-    std::string source_string = original_string;
-    do {
-      beg_seq = source_string.find("${", beg_seq);
-      if (beg_seq > 0 && source_string.at(beg_seq - 1) == '\\') {
-        beg_seq += 2;
-        continue;
-      }
-      if (beg_seq < 0)
-        break;
-      end_seq = source_string.find("}", beg_seq + 2);
-      if (end_seq < 0)
-        break;
-      if (end_seq - (beg_seq + 2) < 0) {
-        beg_seq += 2;
-        continue;
-      }
-      const std::string env_field = source_string.substr(beg_seq + 2, end_seq 
- (beg_seq + 2));
-      const std::string env_field_wrapped = source_string.substr(beg_seq, 
end_seq + 1);
-      if (env_field.empty()) {
-        continue;
-      }
-      const auto strVal = std::getenv(env_field.c_str());
-      std::string env_value;
-      if (strVal != nullptr)
-        env_value = strVal;
-      source_string = replaceAll(source_string, env_field_wrapped, env_value);
-      beg_seq = 0;  // restart
-    } while (beg_seq >= 0);
-
-    source_string = replaceAll(source_string, "\\$", "$");
-
-    return source_string;
-  }
+  std::string replaceMap(std::string source_string, const 
std::map<std::string, std::string> &replace_map);
 
-  static std::string& replaceAll(std::string& source_string, const std::string 
&from_string, const std::string &to_string) {
-    std::size_t loc = 0;
-    std::size_t lastFound;
-    while ((lastFound = source_string.find(from_string, loc)) != 
std::string::npos) {
-      source_string.replace(lastFound, from_string.size(), to_string);
-      loc = lastFound + to_string.size();
-    }
-    return source_string;
-  }
+  std::string replaceEnvironmentVariables(const std::string& original_string);
 
-  inline static bool endsWithIgnoreCase(const std::string &value, const 
std::string & endString) {
+  inline bool endsWithIgnoreCase(const std::string &value, const std::string & 
endString) {
     if (endString.size() > value.size())
       return false;
     return std::equal(endString.rbegin(), endString.rend(), value.rbegin(), 
[](unsigned char lc, unsigned char rc) {return tolower(lc) == tolower(rc);});
   }
 
-  inline static bool endsWith(const std::string &value, const std::string & 
endString) {
+  inline bool endsWith(const std::string &value, const std::string & 
endString) {
     if (endString.size() > value.size())
       return false;
     return std::equal(endString.rbegin(), endString.rend(), value.rbegin());
   }
 
-  inline static std::string hex_ascii(const std::string& in) {
-    int len = in.length();
-    std::string newString;
-    for (int i = 0; i < len; i += 2) {
-      std::string sstr = in.substr(i, 2);
-      char chr = (char) (int) strtol(sstr.c_str(), 0x00, 16);
-      newString.push_back(chr);
-    }
-    return newString;
-  }
-
-  static std::string replaceMap(std::string source_string, const 
std::map<std::string, std::string> &replace_map) {
-    auto result_string = source_string;
-
-    std::vector<std::pair<size_t, std::pair<size_t, std::string>>> 
replacements;
-    for (const auto &replace_pair : replace_map) {
-      size_t replace_pos = 0;
-      while ((replace_pos = source_string.find(replace_pair.first, 
replace_pos)) != std::string::npos) {
-        replacements.emplace_back(std::make_pair(replace_pos, 
std::make_pair(replace_pair.first.length(), replace_pair.second)));
-        replace_pos += replace_pair.first.length();
+  std::string hex_ascii(const std::string& in);
+
+  template<class TChar, class U, typename std::enable_if<std::is_same<typename 
U::value_type, std::basic_string<TChar>>::value>::type* = nullptr>
+  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;
       }
     }
-
-    std::sort(replacements.begin(), replacements.end(), [](const 
std::pair<size_t, std::pair<size_t, std::string>> a,
-        const std::pair<size_t, std::pair<size_t, std::string>> &b) {
-      return a.first > b.first;
-    });
-
-    for (const auto &replacement : replacements) {
-      result_string = source_string.replace(replacement.first, 
replacement.second.first, replacement.second.second);
+    return sstream.str();
+  };
+
+  template<class TChar, class U, typename std::enable_if<std::is_same<typename 
U::value_type, std::basic_string<TChar>>::value>::type* = nullptr>
+  std::basic_string<TChar> join(const TChar* separator, const U& container) {
+    return join(std::basic_string<TChar>(separator), container);
+  };
+
+
+  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>
+  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);
 
 Review comment:
   That could help removing the two template structs that provide 
convert_to_string methods, the price would be two different template 
specialisations (one for char and uint8_t, the other is wchar_t and uint8_t), 
so it can be done, but not sure if that makes it any simpler. 
   
   The rest of the changes are coming from the fact that the this was a class, 
which cannot be extended with template functions. 
   Changing to namespace means that the linkage changes, which naturally need 
to be verified on all platforms, but it cannot be avoided. 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to