PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/retroshare-gui/src/util/stringutil.cpp

https://gitlab.com/g10h4ck/RetroShare
C++ | 339 lines | 250 code | 27 blank | 62 comment | 76 complexity | 0f5754020900e8ac625387a25c17732c MD5 | raw file
Possible License(s): 0BSD, GPL-2.0, AGPL-1.0
  1. /****************************************************************
  2. * This file is distributed under the following license:
  3. *
  4. * Copyright (c) 2008, crypton
  5. * Copyright (c) 2008, Matt Edman, Justin Hipple
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor,
  20. * Boston, MA 02110-1301, USA.
  21. ****************************************************************/
  22. /*
  23. ** \file stringutil.cpp
  24. ** \version $Id: stringutil.cpp 2486 2008-04-05 14:43:08Z edmanm $
  25. ** \brief Common string manipulation functions
  26. */
  27. #include "stringutil.h"
  28. /** Create a QStringList from the array of C-style strings. */
  29. QStringList
  30. char_array_to_stringlist(char **arr, int len)
  31. {
  32. QStringList list;
  33. for (int i = 0; i < len; i++) {
  34. list << QString(arr[i]);
  35. }
  36. return list;
  37. }
  38. /** Conditionally assigns errmsg to str if str is not null and returns false.
  39. * This is a seemingly pointless function, but it saves some messiness in
  40. * methods whose QString *errmsg parameter is optional. */
  41. bool
  42. err(QString *str, const QString &errmsg)
  43. {
  44. if (str) {
  45. *str = errmsg;
  46. }
  47. return false;
  48. }
  49. /** Ensures all characters in str are in validChars. If a character appears
  50. * in str but not in validChars, it will be removed and the resulting
  51. * string returned. */
  52. QString
  53. ensure_valid_chars(const QString &str, const QString &validChars)
  54. {
  55. QString out = str;
  56. for (int i = 0; i < str.length(); i++) {
  57. QChar c = str.at(i);
  58. if (validChars.indexOf(c) < 0) {
  59. out.remove(c);
  60. }
  61. }
  62. return out;
  63. }
  64. /** Scrubs an email address by replacing "@" with " at " and "." with " dot ". */
  65. QString
  66. scrub_email_addr(const QString &email)
  67. {
  68. QString scrubbed = email;
  69. scrubbed = scrubbed.replace("@", " at ");
  70. scrubbed = scrubbed.replace(".", " dot ");
  71. return scrubbed;
  72. }
  73. /** Wraps <b>str</b> at <b>width</b> characters wide, using <b>sep</b> as the
  74. * word separator (" ", for example), and placing the line ending <b>le</b> at
  75. * the end of each line, except the last. */
  76. QString
  77. string_wrap(const QString &str, int width,
  78. const QString &sep, const QString &le)
  79. {
  80. QString wrapped;
  81. int pos, nextsep, wordlen, n;
  82. int seplen = sep.length();
  83. if (str.length() < width) {
  84. return str;
  85. }
  86. pos = 0;
  87. n = width;
  88. while (pos < str.length()) {
  89. /* Get the length of a "word" */
  90. nextsep = str.indexOf(sep, pos);
  91. if (nextsep < 0) {
  92. nextsep = str.length();
  93. }
  94. wordlen = nextsep-pos;
  95. /* Check if there is room for the word on this line */
  96. if (wordlen > n) {
  97. /* Create a new line */
  98. wrapped.append(le);
  99. n = width;
  100. }
  101. /* Add the word to the current line */
  102. wrapped.append(str.mid(pos, wordlen+seplen));
  103. n = n - wordlen - seplen;
  104. pos += wordlen + seplen;
  105. }
  106. return wrapped.trimmed();
  107. }
  108. /** Encodes the bytes in <b>buf</b> as an uppercase hexadecimal string and
  109. * returns the result. This function is derived from base16_encode() in Tor's
  110. * util.c. See LICENSE for details on Tor's license. */
  111. QString
  112. base16_encode(const QByteArray &buf)
  113. {
  114. QString hex;
  115. for (int i = 0; i < buf.size(); i++) {
  116. hex += "0123456789ABCDEF"[((quint8)buf[i]) >> 4];
  117. hex += "0123456789ABCDEF"[((quint8)buf[i]) & 0xf];
  118. }
  119. return hex;
  120. }
  121. /** Given a string <b>str</b>, this function returns a quoted string with all
  122. * '"' and '\' characters escaped with a single '\'. */
  123. QString
  124. string_escape(const QString &str)
  125. {
  126. QString out;
  127. out.append("\"");
  128. for (int i = 0; i < str.length(); i++) {
  129. if (str[i] == '\"' || str[i] == '\\')
  130. out.append('\\');
  131. out.append(str[i]);
  132. }
  133. out.append("\"");
  134. return out;
  135. }
  136. /** Given a quoted string <b>str</b>, this function returns an unquoted,
  137. * unescaped string. <b>str</b> must start and end with an unescaped quote. */
  138. QString
  139. string_unescape(const QString &str, bool *ok)
  140. {
  141. QString out;
  142. /* The string must start and end with an unescaped dquote */
  143. if (str.length() < 2 || !str.startsWith("\"") || !str.endsWith("\"") ||
  144. (str.endsWith("\\\"") && !str.endsWith("\\\\\""))) {
  145. if (ok)
  146. *ok = false;
  147. return QString();
  148. }
  149. for (int i = 1; i < str.length()-1; i++) {
  150. if (str[i] == '\\')
  151. i++;
  152. out.append(str[i]);
  153. }
  154. if (ok)
  155. *ok = true;
  156. return out;
  157. }
  158. /** Parses a series of space-separated key[=value|="value"] tokens from
  159. * <b>str</b> and returns the mappings in a QHash. If <b>str</b> was unable
  160. * to be parsed, <b>ok</b> is set to false. */
  161. QHash<QString,QString>
  162. string_parse_keyvals(const QString &str, bool *ok)
  163. {
  164. int i, len;
  165. bool tmp_ok;
  166. QHash<QString,QString> keyvals;
  167. i = 0;
  168. len = str.length();
  169. while (i < len && str[i].isSpace())
  170. i++; /* Skip initial whitespace */
  171. while (i < len) {
  172. QString key, val;
  173. while (i < len && !str[i].isSpace() && str[i] != '=')
  174. key.append(str[i++]);
  175. if (i < len && str[i] == '=') {
  176. if (++i < len && str[i] == '\"') {
  177. /* The value is wrapped in quotes */
  178. val.append(str[i]);
  179. while (++i < len) {
  180. val.append(str[i]);
  181. if (str[i] == '\\') {
  182. if (++i == len)
  183. goto error;
  184. val.append(str[i]);
  185. } else if (str[i] == '\"') {
  186. i++;
  187. break;
  188. }
  189. }
  190. val = string_unescape(val, &tmp_ok);
  191. if (!tmp_ok)
  192. goto error;
  193. keyvals.insert(key, val);
  194. } else {
  195. /* The value was not wrapped in quotes */
  196. while (i < len && !str[i].isSpace())
  197. val.append(str[i++]);
  198. keyvals.insert(key, val);
  199. }
  200. } else {
  201. /* The key had no value */
  202. keyvals.insert(key, QString(""));
  203. }
  204. while (i < len && str[i].isSpace())
  205. i++;
  206. }
  207. if (ok)
  208. *ok = true;
  209. return keyvals;
  210. error:
  211. if (ok)
  212. *ok = false;
  213. return QHash<QString,QString>();
  214. }
  215. /** Parses a series of command line arguments from <b>str</b>. If <b>str</b>
  216. * was unable to be parsed, <b>ok</b> is set to false. */
  217. QStringList
  218. string_parse_arguments(const QString &str, bool *ok)
  219. {
  220. QStringList args;
  221. int i, len;
  222. bool tmp_ok;
  223. i = 0;
  224. len = str.length();
  225. while (i < len && str[i].isSpace())
  226. i++; /* Skip initial whitespace */
  227. while (i < len) {
  228. QString arg;
  229. if (str[i] == '\"') {
  230. /* The value is wrapped in quotes */
  231. arg.append(str[i]);
  232. while (++i < len) {
  233. arg.append(str[i]);
  234. if (str[i] == '\\') {
  235. if (++i == len)
  236. goto error;
  237. arg.append(str[i]);
  238. } else if (str[i] == '\"') {
  239. i++;
  240. break;
  241. }
  242. }
  243. arg = string_unescape(arg, &tmp_ok);
  244. if (!tmp_ok)
  245. goto error;
  246. args << arg;
  247. } else {
  248. /* The value was not wrapped in quotes */
  249. while (i < len && !str[i].isSpace())
  250. arg.append(str[i++]);
  251. args << arg;
  252. }
  253. while (i < len && str[i].isSpace())
  254. i++;
  255. }
  256. if (ok)
  257. *ok = true;
  258. return args;
  259. error:
  260. if (ok)
  261. *ok = false;
  262. return QStringList();
  263. }
  264. /** Formats the list of command line arguments in <b>args</b> as a string.
  265. * Arguments that contain ' ', '\', or '"' tokens will be escaped and
  266. * wrapped in double quotes. */
  267. QString
  268. string_format_arguments(const QStringList &args)
  269. {
  270. QStringList out;
  271. foreach (QString arg, args) {
  272. if (arg.contains("\"") || arg.contains("\\") || arg.contains(" "))
  273. out << string_escape(arg);
  274. else
  275. out << arg;
  276. }
  277. return out.join(" ");
  278. }
  279. /** Returns true if <b>str</b> is a valid hexademical string. Returns false
  280. * otherwise. */
  281. bool
  282. string_is_hex(const QString &str)
  283. {
  284. for (int i = 0; i < str.length(); i++) {
  285. char c = str[i].toUpper().toLatin1();
  286. if ((c < 'A' || c > 'F') && (c < '0' || c > '9'))
  287. return false;
  288. }
  289. return true;
  290. }
  291. namespace RsStringUtil
  292. {
  293. QString CopyLines(const QString &s, quint16 lines)
  294. {
  295. int index = -1;
  296. for (int i = 0; i < lines; ++i) {
  297. index = s.indexOf("\n", index + 1);
  298. if (index == -1) {
  299. break;
  300. }
  301. }
  302. if (index != -1) {
  303. return s.left(index);
  304. }
  305. return s;
  306. }
  307. }