phrocker 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_r292914049
 
 

 ##########
 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:
   This seems to enforce a semantic. I think basic stringstream assumes 
character if it is one. In that case, I don't see the need for the complexity 
as you could have one function that assumes what streamstream does and an 
overload that allows uint8_t to be interpreted with to_string. Two functions, 
much simpler and cleaner. Removing the rest of the changes will alleviate any 
linker issues. 

----------------------------------------------------------------
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