text: #include <algorithm>
  #include <cctype>
  #include <sstream>
  #include "string.h"
  
  using namespace std;
  
  namespace Utils::String {
      bool replace(string &str, const string &from, const string &to) {
          size_t start_pos = str.find(from);
          if (start_pos == string::npos)
              return false;
          str.replace(start_pos, from.length(), to);
          return true;
      }
  
      void replace_all(string &str, const string &from, const string &to) {
          bool success = Utils::String::replace(str, from, to);
  
          while (success) {
              success = Utils::String::replace(str, from, to);
          }
      }
  
      void to_lower(string &str) {
          transform(str.begin(), str.end(), str.begin(),
                    [](unsigned char c) { return tolower(c); });
      }
  
      string to_lower_copy(const string &str) {
          string newString = str;
  
          to_lower(newString);
          return newString;
      }
  
      vector<std::string> split(const std::string &str, const char &delimiter) {
          stringstream ss(str);
          vector<string> result;
  
          while (ss.good()) {
              string substr;
              getline(ss, substr, delimiter);
              result.push_back(substr);
          }
  
          return result;
      }
  
      string join(const vector<string> &strings, const string &delimiter) {
          size_t total = 0;
          size_t count = 0;
  
          for (const auto &s : strings)
              total += s.size();
  
          string all;
  
          all.reserve(total + 1);
          for (const auto &s : strings) {
              count++;
              all.append(s);
  
              if (count != strings.size()) {
                  all.append(delimiter);
              }
          }
  
          return all;
      }
  
      string ltrim(const string &s) {
          size_t start = s.find_first_not_of(WHITESPACE);
          return (start == string::npos) ? "" : s.substr(start);
      }
  
      string rtrim(const string &s) {
          size_t end = s.find_last_not_of(WHITESPACE);
          return (end == string::npos) ? "" : s.substr(0, end + 1);
      }
  
      string trim(const string &s) {
          return rtrim(ltrim(s));
      }
  
      size_t get_hash(const string &s) {
          return std::hash<std::string>{}(s);
      }
  }