String.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // Copyright 2017, University of Freiburg,
  2. // Chair of Algorithms and Data Structures.
  3. // Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
  4. #ifndef UTIL_STRING_H_
  5. #define UTIL_STRING_H_
  6. #include <algorithm>
  7. #include <cstring>
  8. #include <sstream>
  9. #include <string>
  10. #include <vector>
  11. namespace util {
  12. // _____________________________________________________________________________
  13. inline std::string urlDecode(const std::string& encoded) {
  14. std::string decoded;
  15. for (size_t i = 0; i < encoded.size(); ++i) {
  16. char c = encoded[i];
  17. if (c == '%') {
  18. std::string ah = encoded.substr(i + 1, 2);
  19. char* nonProced = 0;
  20. char hexVal = strtol(ah.c_str(), &nonProced, 16);
  21. if (ah.find_first_of("+-") > 1 && ah.size() - strlen(nonProced) == 2) {
  22. c = hexVal;
  23. i += 2;
  24. }
  25. } else if (c == '+') {
  26. c = ' ';
  27. }
  28. decoded += c;
  29. }
  30. return decoded;
  31. }
  32. // _____________________________________________________________________________
  33. inline std::string jsonStringEscape(const std::string& unescaped) {
  34. std::string escaped;
  35. for (size_t i = 0; i < unescaped.size(); ++i) {
  36. if (unescaped[i] == '"' || unescaped[i] == '\\') {
  37. escaped += "\\";
  38. }
  39. if (iscntrl(unescaped[i])) {
  40. escaped += " ";
  41. }
  42. escaped += unescaped[i];
  43. }
  44. return escaped;
  45. }
  46. // _____________________________________________________________________________
  47. inline bool replace(std::string& subj, const std::string& from,
  48. const std::string& to) {
  49. if (from.empty()) return false;
  50. size_t start_pos = subj.find(from);
  51. if (start_pos != std::string::npos) {
  52. subj.replace(start_pos, from.length(), to);
  53. return true;
  54. }
  55. return false;
  56. }
  57. // _____________________________________________________________________________
  58. inline bool replaceAll(std::string& subj, const std::string& from,
  59. const std::string& to) {
  60. if (from.empty()) return false;
  61. bool found = false;
  62. size_t s = subj.find(from, 0);
  63. for (; s != std::string::npos; s = subj.find(from, s + to.length())) {
  64. found = true;
  65. subj.replace(s, from.length(), to);
  66. }
  67. return found;
  68. }
  69. // _____________________________________________________________________________
  70. inline std::string unixBasename(const std::string& pathname) {
  71. return {std::find_if(pathname.rbegin(), pathname.rend(),
  72. [](char c) { return c == '/'; })
  73. .base(),
  74. pathname.end()};
  75. }
  76. // _____________________________________________________________________________
  77. template <typename T>
  78. inline std::string toString(T obj) {
  79. std::stringstream ss;
  80. ss << obj;
  81. return ss.str();
  82. }
  83. // _____________________________________________________________________________
  84. inline std::vector<std::string> split(std::string in, char sep) {
  85. std::stringstream ss(in);
  86. std::vector<std::string> ret(1);
  87. while (std::getline(ss, ret.back(), sep)) {
  88. ret.push_back("");
  89. }
  90. ret.pop_back();
  91. return ret;
  92. }
  93. // _____________________________________________________________________________
  94. inline std::string ltrim(std::string str) {
  95. str.erase(0, str.find_first_not_of(" \t\n\v\f\r"));
  96. return str;
  97. }
  98. // _____________________________________________________________________________
  99. inline std::string rtrim(std::string str) {
  100. str.erase(str.find_last_not_of(" \t\n\v\f\r") + 1);
  101. return str;
  102. }
  103. // _____________________________________________________________________________
  104. inline std::string trim(std::string str) { return ltrim(rtrim(str)); }
  105. // _____________________________________________________________________________
  106. inline size_t editDist(const std::string& s1, const std::string& s2) {
  107. // https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C++
  108. size_t len1 = s1.size();
  109. size_t len2 = s2.size();
  110. std::vector<size_t> cur(len2 + 1);
  111. std::vector<size_t> prev(len2 + 1);
  112. for (size_t i = 0; i < prev.size(); i++) prev[i] = i;
  113. for (size_t i = 0; i < len1; i++) {
  114. cur[0] = i + 1;
  115. for (size_t j = 0; j < len2; j++) {
  116. cur[j + 1] =
  117. std::min(prev[1 + j] + 1,
  118. std::min(cur[j] + 1, prev[j] + (s1[i] == s2[j] ? 0 : 1)));
  119. }
  120. std::swap(cur, prev);
  121. }
  122. return prev[len2];
  123. }
  124. // _____________________________________________________________________________
  125. inline size_t prefixEditDist(const std::string& prefix, const std::string& s,
  126. size_t deltaMax) {
  127. // https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C++
  128. size_t len1 = prefix.size();
  129. size_t len2 = std::min(s.size(), prefix.size() + deltaMax + 1);
  130. std::vector<size_t> d((len1 + 1) * (len2 + 1));
  131. d[0] = 0;
  132. for (size_t i = 1; i <= len1; ++i) d[i * (len2 + 1)] = i;
  133. for (size_t i = 1; i <= len2; ++i) d[ i] = i;
  134. for (size_t i = 1; i <= len1; i++) {
  135. for (size_t j = 1; j <= len2; j++) {
  136. d[i * (len2 + 1) + j] = std::min(std::min(d[(i - 1) * (len2 + 1) + j] + 1, d[i * (len2 + 1) + j - 1] + 1),
  137. d[(i - 1) * (len2 + 1) + j - 1] + (prefix[i - 1] == s[j - 1] ? 0 : 1));
  138. }
  139. }
  140. // take min of last row
  141. size_t deltaMin = std::max(std::max(deltaMax + 1, prefix.size()), s.size());
  142. for (size_t i = 0; i <= len2; i++) {
  143. if (d[len1 * (len2 + 1) + i] < deltaMin) deltaMin = d[len1 * (len2 + 1) + i];
  144. }
  145. return deltaMin;
  146. }
  147. // _____________________________________________________________________________
  148. inline size_t prefixEditDist(const std::string& prefix, const std::string& s) {
  149. return prefixEditDist(prefix, s, s.size());
  150. }
  151. // _____________________________________________________________________________
  152. inline std::string toUpper(std::string str) {
  153. std::transform(str.begin(), str.end(),str.begin(), toupper);
  154. return str;
  155. }
  156. // _____________________________________________________________________________
  157. inline std::string toLower(std::string str) {
  158. std::transform(str.begin(), str.end(),str.begin(), tolower);
  159. return str;
  160. }
  161. // _____________________________________________________________________________
  162. template <class Iter>
  163. inline std::string implode(Iter begin, const Iter& end, const char* del) {
  164. std::stringstream ss;
  165. size_t i = 0;
  166. while (begin != end) {
  167. if (i != 0) ss << del;
  168. ss << *begin;
  169. begin++;
  170. i++;
  171. }
  172. return ss.str();
  173. }
  174. // _____________________________________________________________________________
  175. inline std::string normalizeWhiteSpace(const std::string& input) {
  176. std::string ret;
  177. bool ws = false;
  178. for (size_t i = 0; i < input.size(); i++) {
  179. if (std::isspace(input[i])) {
  180. if (!ws) {
  181. ret += " ";
  182. ws = true;
  183. }
  184. continue;
  185. } else {
  186. ws = false;
  187. ret += input[i];
  188. }
  189. }
  190. return ret;
  191. }
  192. // _____________________________________________________________________________
  193. template <typename T>
  194. inline std::string implode(const std::vector<T>& vec, const char* del) {
  195. return implode(vec.begin(), vec.end(), del);
  196. }
  197. }
  198. #endif // UTIL_STRING_H_