ManaPlus
stringutils.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2007-2009 The Mana World Development Team
4  * Copyright (C) 2009-2010 The Mana Developers
5  * Copyright (C) 2011-2019 The ManaPlus Developers
6  *
7  * This file is part of The ManaPlus Client.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include "utils/stringutils.h"
24 
25 #include "const/utils/utf8.h"
26 
27 #ifdef DYECMD
28 #include "utils/cast.h"
29 #else // DYECMD
30 #include "resources/iteminfo.h"
31 #include "resources/db/itemdb.h"
32 #endif // DYECMD
33 
34 #include "utils/gettext.h"
35 #include "utils/foreach.h"
36 
37 #include <algorithm>
38 #include <sstream>
39 
40 #ifdef WIN32
41 #include <sys/time.h>
42 #endif // WIN32
43 
44 #include "debug.h"
45 
46 std::string &trim(std::string &str)
47 {
48  size_t pos = str.find_last_not_of(' ');
49  if (pos != std::string::npos)
50  {
51  str.erase(pos + 1);
52  pos = str.find_first_not_of(' ');
53 
54  if (pos != std::string::npos)
55  str.erase(0, pos);
56  }
57  else
58  {
59  // There is nothing else but whitespace in the string
60  str.clear();
61  }
62  return str;
63 }
64 
65 std::string &toLower(std::string &str)
66 {
67  std::transform(str.begin(), str.end(), str.begin(), &tolower);
68  return str;
69 }
70 
71 std::string &toUpper(std::string &str)
72 {
73  std::transform(str.begin(), str.end(), str.begin(), &toupper);
74  return str;
75 }
76 
77 unsigned int atox(const std::string &str)
78 {
79  unsigned int value = 0;
80  if (sscanf(str.c_str(), "0x%06x", &value) != 0)
81  return value;
82  return 0;
83 }
84 
85 const char *ipToString(const uint32_t address)
86 {
87  static char asciiIP[18];
88 
89  snprintf(asciiIP, sizeof(asciiIP), "%i.%i.%i.%i",
90  CAST_U8(address),
91  CAST_U8(address >> 8),
92  CAST_U8(address >> 16),
93  CAST_U8(address >> 24));
94  asciiIP[17] = 0;
95 
96  return asciiIP;
97 }
98 
99 std::string strprintf(const char *const format, ...)
100 {
101  char buf[257];
102  va_list args;
103  va_start(args, format);
104  size_t nb = vsnprintf(buf, 256, format, args);
105  buf[256] = 0;
106  va_end(args);
107  if (nb < 256)
108  return buf;
109 
110  // The static size was not big enough, try again with a dynamic allocation.
111  ++nb;
112  char *buf2 = new char[nb];
113  va_start(args, format);
114  vsnprintf(buf2, nb, format, args);
115  va_end(args);
116  std::string res(buf2);
117  delete [] buf2;
118  return res;
119 }
120 
121 std::string removeColors(std::string msg)
122 {
123  for (unsigned int f = 0; f < msg.length() - 2 && msg.length() > 2; f++)
124  {
125  while (msg.length() > f + 2 && msg.at(f) == '#'
126  && msg.at(f + 1) == '#')
127  {
128  msg = msg.erase(f, 3);
129  }
130  }
131  return msg;
132 }
133 
134 int compareStrI(const std::string &a, const std::string &b)
135 {
136  std::string::const_iterator itA = a.begin();
137  const std::string::const_iterator endA = a.end();
138  std::string::const_iterator itB = b.begin();
139  const std::string::const_iterator endB = b.end();
140 
141  for (; itA < endA && itB < endB; ++itA, ++itB)
142  {
143  const int comp = tolower(*itA) - tolower(*itB);
144  if (comp != 0)
145  return comp;
146  }
147 
148  // Check string lengths
149  if (itA == endA && itB == endB)
150  return 0;
151  else if (itA == endA)
152  return -1;
153  else
154  return 1;
155 }
156 
157 const std::string findSameSubstring(const std::string &restrict str1,
158  const std::string &restrict str2)
159 {
160  const int minLength = str1.length() > str2.length()
161  ? CAST_S32(str2.length()) : CAST_S32(str1.length());
162  for (int f = 0; f < minLength; f ++)
163  {
164  if (str1.at(f) != str2.at(f))
165  return str1.substr(0, f);
166  }
167  return str1.substr(0, minLength);
168 }
169 
170 const std::string findSameSubstringI(const std::string &restrict s1,
171  const std::string &restrict s2)
172 {
173  std::string str1 = s1;
174  std::string str2 = s2;
175  toLower(str1);
176  toLower(str2);
177 
178  const size_t minLength = str1.length() > str2.length()
179  ? str2.length() : str1.length();
180  for (size_t f = 0; f < minLength; f ++)
181  {
182  if (str1.at(f) != str2.at(f))
183  return s1.substr(0, f);
184  }
185  return s1.substr(0, minLength);
186 }
187 
188 size_t findI(std::string str, std::string subStr)
189 {
190  str = toLower(str);
191  subStr = toLower(subStr);
192  return str.find(subStr);
193 }
194 
195 size_t findI(std::string text, const StringVect &list)
196 {
197  toLower(text);
198  FOR_EACH (StringVectCIter, i, list)
199  {
200  std::string subStr = *i;
201  subStr = toLower(subStr);
202  const size_t idx = text.find(subStr);
203  if (idx != std::string::npos)
204  return idx;
205  }
206  return std::string::npos;
207 }
208 
209 size_t findAny(const std::string &restrict text,
210  const std::string &restrict chars,
211  const size_t pos)
212 {
213  size_t idx = std::string::npos;
214  const size_t sz = chars.size();
215  for (size_t f = 0; f < sz; f ++)
216  {
217  const size_t idx2 = text.find(chars[f], pos);
218  if (idx2 != std::string::npos && idx2 < idx)
219  idx = idx2;
220  }
221  return idx;
222 }
223 
224 namespace
225 {
226  unsigned int base = 94;
227  unsigned int start = 33;
228 } // namespace
229 
230 const std::string encodeStr(unsigned int value, const unsigned int size)
231 {
232  std::string buf;
233 
234  do
235  {
236  buf += CAST_S8(value % base + start);
237  value /= base;
238  }
239  while (value != 0U);
240 
241  while (buf.length() < size)
242  buf += CAST_S8(start);
243  return buf;
244 }
245 
246 
247 unsigned int decodeStr(const std::string &str)
248 {
249  if (str.empty())
250  return 0;
251 
252  int res = str[0] - start;
253  int mult = 1;
254  for (size_t f = 1; f < str.length(); f ++)
255  {
256  mult *= base;
257  res = res + (str[f] - start) * mult;
258  }
259  return res;
260 }
261 
262 std::string extractNameFromSprite(std::string str)
263 {
264  const size_t pos1 = str.rfind('.');
265  if (pos1 != std::string::npos)
266  {
267  size_t pos2 = str.rfind('/');
268  const size_t pos3 = str.rfind('\\');
269  if (pos3 != std::string::npos)
270  {
271  if (pos2 == std::string::npos || pos3 > pos2)
272  pos2 = pos3;
273  }
274  if (pos2 == std::string::npos)
275  pos2 = CAST_SIZE(-1);
276 
277  const int size = CAST_S32(pos1) - CAST_S32(pos2) - 1;
278  if (size > 0)
279  str = str.substr(pos2 + 1, size);
280  }
281  return str;
282 }
283 
284 std::string removeSpriteIndex(std::string str)
285 {
286  const size_t pos1 = str.rfind('[');
287 
288  if (pos1 != std::string::npos)
289  {
290  size_t pos2 = str.rfind('/');
291  const size_t pos3 = str.rfind('\\');
292  if (pos3 != std::string::npos)
293  {
294  if (pos2 == std::string::npos || pos3 > pos2)
295  pos2 = pos3;
296  }
297  if (pos2 == std::string::npos)
298  pos2 = CAST_SIZE(-1);
299 
300  const int size = CAST_S32(pos1) - CAST_S32(pos2) - 1;
301  if (size > 0)
302  str = str.substr(pos2 + 1, size);
303  }
304  return str;
305 }
306 
307 const char* getSafeUtf8String(const std::string &text)
308 {
309  const size_t sz = text.size();
310  const size_t size = sz + UTF8_MAX_SIZE;
311  char *const buf = new char[size];
312  memcpy(buf, text.c_str(), sz);
313  memset(buf + sz, 0, UTF8_MAX_SIZE);
314  return buf;
315 }
316 
317 void getSafeUtf8String(std::string text, char *const buf)
318 {
319  if (buf == nullptr)
320  return;
321  const size_t sz = text.size();
322  const size_t size = sz + UTF8_MAX_SIZE;
323  if (size > 65500)
324  {
325  text = text.substr(0, 65500);
326  const size_t sz1 = text.size();
327  memcpy(buf, text.c_str(), sz1);
328  memset(buf + sz1, 0, UTF8_MAX_SIZE);
329  }
330  else
331  {
332  memcpy(buf, text.c_str(), sz);
333  memset(buf + sz, 0, UTF8_MAX_SIZE);
334  }
335 }
336 
337 std::string getFileName(const std::string &path)
338 {
339  size_t pos1 = path.rfind('/');
340  const size_t pos2 = path.rfind('\\');
341  if (pos1 == std::string::npos ||
342  (pos2 != std::string::npos && pos2 > pos1))
343  {
344  pos1 = pos2;
345  }
346 
347  if (pos1 == std::string::npos)
348  return path;
349  return path.substr(pos1 + 1);
350 }
351 
352 std::string getFileDir(const std::string &path)
353 {
354  size_t pos1 = path.rfind('/');
355  const size_t pos2 = path.rfind('\\');
356  if (pos1 == std::string::npos ||
357  (pos2 != std::string::npos && pos2 > pos1))
358  {
359  pos1 = pos2;
360  }
361 
362  if (pos1 == std::string::npos)
363  return path;
364  return path.substr(0, pos1);
365 }
366 
367 std::string& replaceAll(std::string& context,
368  const std::string &restrict from,
369  const std::string &restrict to)
370 {
371  if (from.empty())
372  return context;
373  size_t lookHere = 0;
374  size_t foundHere;
375  const size_t fromSize = from.size();
376  const size_t toSize = to.size();
377  while ((foundHere = context.find(from, lookHere)) != std::string::npos)
378  {
379  context.replace(foundHere, fromSize, to);
380  lookHere = foundHere + toSize;
381  }
382  return context;
383 }
384 
385 void replaceRecursiveAll(std::string& context,
386  const std::string &restrict from,
387  const char to)
388 {
389  size_t lookHere = 0;
390  size_t foundHere;
391  const size_t fromSize = from.size();
392  while ((foundHere = context.find(from, lookHere)) != std::string::npos)
393  {
394  context.replace(foundHere, fromSize, 1, to);
395  lookHere = foundHere;
396  }
397 }
398 
399 bool getBoolFromString(const std::string &text)
400 {
401  std::string txt = text;
402  toLower(trim(txt));
403  if (txt == "true" || txt == "yes" || txt == "on" || txt == "1")
404  return true;
405  else if (txt == "false" || txt == "no" || txt == "off" || txt == "0")
406  return false;
407  else
408  return static_cast<bool>(atoi(txt.c_str()));
409 }
410 
411 void replaceSpecialChars(std::string &text)
412 {
413  size_t pos1 = text.find('&');
414  while (pos1 != std::string::npos)
415  {
416  const size_t idx = pos1 + 1;
417  const size_t sz = text.size();
418  if (idx >= sz)
419  break;
420 
421  size_t f;
422  for (f = idx; f < sz; f ++)
423  {
424  if (text[f] < '0' || text[f] > '9')
425  break;
426  }
427  if (idx + 1 < f && text[f] == ';')
428  {
429  std::string str(" ");
430  str[0] = CAST_S8(atoi(text.substr(
431  idx, f - idx).c_str()));
432  text = text.substr(0, pos1).append(str).append(text.substr(f + 1));
433  pos1 += 1;
434  }
435  else
436  {
437  pos1 = f + 1;
438  }
439 
440  pos1 = text.find('&', pos1);
441  }
442 }
443 
444 std::string normalize(const std::string &name)
445 {
446  std::string normalized = name;
447  return toLower(trim(normalized));
448 }
449 
450 void splitToIntSet(std::set<int> &tokens,
451  const std::string &text,
452  const char separator)
453 {
454  std::stringstream ss(text);
455  std::string item;
456  while (std::getline(ss, item, separator))
457  tokens.insert(atoi(item.c_str()));
458 }
459 
460 std::list<int> splitToIntList(const std::string &text,
461  const char separator)
462 {
463  std::list<int> tokens;
464  std::stringstream ss(text);
465  std::string item;
466  while (std::getline(ss, item, separator))
467  tokens.push_back(atoi(item.c_str()));
468 
469  return tokens;
470 }
471 
472 std::list<std::string> splitToStringList(const std::string &text,
473  const char separator)
474 {
475  std::list<std::string> tokens;
476  std::stringstream ss(text);
477  std::string item;
478  while (std::getline(ss, item, separator))
479  tokens.push_back(item);
480 
481  return tokens;
482 }
483 
485  const std::string &text,
486  const char separator)
487 {
488  std::stringstream ss(text);
489  std::string item;
490  while (std::getline(ss, item, separator))
491  {
492  item = trim(item);
493  if (!item.empty())
494  tokens.push_back(item);
495  }
496 }
497 
498 void splitToStringSet(std::set<std::string> &tokens,
499  const std::string &text,
500  const char separator)
501 {
502  std::stringstream ss(text);
503  std::string item;
504  while (std::getline(ss, item, separator))
505  {
506  item = trim(item);
507  if (!item.empty())
508  tokens.insert(item);
509  }
510 }
511 
512 void splitToIntVector(STD_VECTOR<int> &tokens,
513  const std::string &text,
514  const char separator)
515 {
516  std::stringstream ss(text);
517  std::string item;
518  while (std::getline(ss, item, separator))
519  {
520  item = trim(item);
521  if (!item.empty())
522  tokens.push_back(atoi(item.c_str()));
523  }
524 }
525 
526 std::string combineDye(std::string file,
527  const std::string &dye)
528 {
529  if (dye.empty())
530  return file;
531  const size_t pos = file.find_last_of('|');
532  if (pos != std::string::npos)
533  return file.substr(0, pos).append("|").append(dye);
534  return file.append("|").append(dye);
535 }
536 
537 std::string combineDye2(std::string file,
538  const std::string &dye)
539 {
540  if (dye.empty())
541  return file;
542 
543  const size_t pos = file.find_last_of('|');
544  if (pos != std::string::npos)
545  {
546  const std::string dye1 = file.substr(pos + 1);
547  std::string str;
548  file = file.substr(0, pos);
549  const std::list<std::string> list1 = splitToStringList(dye1, ';');
550  const std::list<std::string> list2 = splitToStringList(dye, ';');
551  for (std::list<std::string>::const_iterator it1 = list1.begin(),
552  it2 = list2.begin(), it1_end = list1.end(), it2_end = list2.end();
553  it1 != it1_end && it2 != it2_end; ++it1, ++it2)
554  {
555  str.append(*it1).append(":").append(*it2).append(";");
556  }
557  return file.append("|").append(str);
558  }
559  return file;
560 }
561 
562 std::string combineDye3(std::string file,
563  const std::string &dye)
564 {
565  if (dye.empty())
566  return file;
567 
568  const size_t pos = file.find_last_of('|');
569  if (pos != std::string::npos)
570  {
571  const std::string dye1 = file.substr(pos + 1);
572  std::string str;
573  file = file.substr(0, pos);
574  const std::list<std::string> list1 = splitToStringList(dye1, ';');
575  const std::list<std::string> list2 = splitToStringList(dye, ';');
576  for (std::list<std::string>::const_iterator it1 = list1.begin(),
577  it2 = list2.begin(), it1_end = list1.end(), it2_end = list2.end();
578  it1 != it1_end && it2 != it2_end; ++it1, ++it2)
579  {
580  str.append(*it1).append(":").append(*it2).append(";");
581  }
582  return file.append("|").append(str);
583  }
584  if (file.empty())
585  return file;
586  return file.append("|").append(dye);
587 }
588 
589 std::string packList(const std::list<std::string> &list)
590 {
591  std::list<std::string>::const_iterator i = list.begin();
592  std::string str;
593  while (i != list.end())
594  {
595  str.append(*i).append("|");
596  ++ i;
597  }
598  const size_t sz = str.size();
599  if (sz > 1)
600  str = str.substr(0, sz - 1);
601  return str;
602 }
603 
604 std::list<std::string> unpackList(const std::string &str)
605 {
606  return splitToStringList(str, '|');
607 }
608 
609 std::string stringToHexPath(const std::string &str)
610 {
611  if (str.empty())
612  return "";
613 
614  std::string hex = strprintf("%%%2x/", CAST_U32(str[0]));
615  for (unsigned f = 1, fsz = CAST_U32(str.size());
616  f < fsz; f ++)
617  {
618  hex.append(strprintf("%%%2x", CAST_U32(str[f])));
619  }
620  return hex;
621 }
622 
623 void deleteCharLeft(std::string &str,
624  unsigned *const pos)
625 {
626  if (pos == nullptr)
627  return;
628 
629  while (*pos > 0)
630  {
631  (*pos)--;
632  const int v = str[*pos];
633  str.erase(*pos, 1);
634  if ((v & 192) != 128)
635  break;
636  }
637 }
638 
639 bool findLast(const std::string &restrict str1,
640  const std::string &restrict str2)
641 {
642  const size_t s1 = str1.size();
643  const size_t s2 = str2.size();
644  if (s1 < s2)
645  return false;
646  if (str1.substr(s1 - s2) == str2)
647  return true;
648  return false;
649 }
650 
651 bool findFirst(const std::string &restrict str1,
652  const std::string &restrict str2)
653 {
654  const size_t s1 = str1.size();
655  const size_t s2 = str2.size();
656  if (s1 < s2)
657  return false;
658  if (str1.substr(0, s2) == str2)
659  return true;
660  return false;
661 }
662 
663 bool findCutLast(std::string &restrict str1,
664  const std::string &restrict str2)
665 {
666  const size_t s1 = str1.size();
667  const size_t s2 = str2.size();
668  if (s1 < s2)
669  return false;
670  if (str1.substr(s1 - s2) == str2)
671  {
672  str1 = str1.substr(0, s1 - s2);
673  return true;
674  }
675  return false;
676 }
677 
678 void cutLast(std::string &restrict str1,
679  const std::string &restrict str2)
680 {
681  const size_t s1 = str1.size();
682  const size_t s2 = str2.size();
683  if (s1 < s2)
684  return;
685  if (str1.substr(s1 - s2) == str2)
686  str1 = str1.substr(0, s1 - s2);
687 }
688 
689 bool findCutFirst(std::string &restrict str1,
690  const std::string &restrict str2)
691 {
692  const size_t s1 = str1.size();
693  const size_t s2 = str2.size();
694  if (s1 < s2)
695  return false;
696  if (str1.substr(0, s2) == str2)
697  {
698  str1 = str1.substr(s2);
699  return true;
700  }
701  return false;
702 }
703 
704 void cutFirst(std::string &restrict str1,
705  const std::string &restrict str2)
706 {
707  const size_t s1 = str1.size();
708  const size_t s2 = str2.size();
709  if (s1 < s2)
710  return;
711  if (str1.substr(0, s2) == str2)
712  str1 = str1.substr(s2);
713 }
714 
715 std::string &removeProtocol(std::string &url)
716 {
717  const size_t i = url.find("://");
718  if (i != std::string::npos)
719  url = url.substr(i + 3);
720  return url;
721 }
722 
723 bool strStartWith(const std::string &restrict str1,
724  const std::string &restrict str2)
725 {
726  const size_t sz2 = str2.size();
727  if (str1.size() < sz2)
728  return false;
729  return str1.substr(0, sz2) == str2;
730 }
731 
732 std::string getDateString()
733 {
734  char buffer[80];
735  time_t rawtime;
736  time(&rawtime);
737  const tm *const timeinfo = localtime(&rawtime);
738 
739  strftime(buffer, 79, "%Y-%m-%d", timeinfo);
740  return std::string(buffer);
741 }
742 
743 std::string getDateTimeString()
744 {
745  char buffer[80];
746  time_t rawtime;
747  time(&rawtime);
748  const tm *const timeinfo = localtime(&rawtime);
749 
750  strftime(buffer, 79, "%Y-%m-%d %H:%M:%S", timeinfo);
751  return std::string(buffer);
752 }
753 
754 signed char parseBoolean(const std::string &value)
755 {
756  std::string txt = value;
757  toLower(trim(txt));
758  if (txt == "true" || txt == "yes" || txt == "on" || txt == "1")
759  return 1;
760  else if (txt == "false" || txt == "no" || txt == "off" || txt == "0")
761  return 0;
762  else
763  return -1;
764 }
765 
766 std::string encodeLinkText(std::string data)
767 {
768  return replaceAll(data, "|", "\342\235\230");
769 }
770 
771 std::string decodeLinkText(std::string data)
772 {
773  return replaceAll(data, "\342\235\230", "|");
774 }
775 
776 std::string toStringPrint(const unsigned int val)
777 {
778  static char str[100];
779  snprintf(str, sizeof(str), "%u 0x%x", val, val);
780  str[99] = 0;
781  return str;
782 }
783 
784 std::string toString(uint32_t num)
785 {
786  char buf[30];
787  buf[29] = '\0';
788  size_t idx = 28;
789  do
790  buf[idx--] = CAST_8((num % 10) + '0');
791  while ((num /= 10) != 0);
792  return buf + idx + 1;
793 }
794 
795 std::string toString(uint64_t num)
796 {
797  char buf[100];
798  buf[99] = '\0';
799  size_t idx = 98;
800  do
801  buf[idx--] = CAST_8((num % 10) + '0');
802  while ((num /= 10) != 0);
803  return buf + idx + 1;
804 }
805 
806 std::string toString(uint16_t num)
807 {
808  char buf[10];
809  buf[9] = '\0';
810  size_t idx = 8;
811  do
812  buf[idx--] = CAST_8((num % 10) + '0');
813  while ((num /= 10) != 0);
814  return buf + idx + 1;
815 }
816 
817 std::string toString(unsigned char num)
818 {
819  char buf[5];
820  buf[4] = '\0';
821  size_t idx = 3;
822  do
823  buf[idx--] = CAST_8((num % 10) + '0');
824  while ((num /= 10) != 0);
825  return buf + idx + 1;
826 }
827 
828 std::string toString(int32_t num)
829 {
830  char buf[30];
831  bool useSign(false);
832  buf[29] = '\0';
833  size_t idx = 28;
834 
835  if (num < 0)
836  {
837  useSign = true;
838  num = -num;
839  }
840  do
841  buf[idx--] = CAST_8((num % 10) + '0');
842  while ((num /= 10) != 0);
843  if (useSign)
844  buf[idx--] = '-';
845  return buf + idx + 1;
846 }
847 
848 std::string toString(const float num)
849 {
850  return strprintf("%f", num);
851 }
852 
853 std::string toString(const double num)
854 {
855  return strprintf("%f", static_cast<float>(num));
856 }
857 
858 bool isDigit(const std::string &str)
859 {
860  if (str.empty())
861  return false;
862  const size_t sz = str.size();
863  for (size_t f = 0; f < sz; f ++)
864  {
865  const char &chr = str[f];
866  if (chr < '0' || chr > '9')
867  return false;
868  }
869  return true;
870 }
871 
872 void secureChatCommand(std::string &str)
873 {
874  if (str[0] == '/' || str[0] == '@' || str[0] == '#')
875  str = "_" + str;
876 }
877 
878 bool parse2Int(const std::string &args,
879  int &x,
880  int &y)
881 {
882  bool isValid = false;
883  size_t pos = args.find(' ');
884  if (pos == std::string::npos)
885  pos = args.find(',');
886  if (pos != std::string::npos)
887  {
888  if (pos + 1 < args.length())
889  {
890  x = atoi(args.substr(0, pos).c_str());
891  y = atoi(args.substr(pos + 1, args.length()).c_str());
892  isValid = true;
893  }
894  }
895  return isValid;
896 }
897 
898 bool parse2Str(const std::string &args,
899  std::string &str1,
900  std::string &str2)
901 {
902  bool isValid = false;
903  size_t pos = args.find(' ');
904  if (pos == std::string::npos)
905  pos = args.find(',');
906  if (pos != std::string::npos)
907  {
908  if (pos + 1 < args.length())
909  {
910  str1 = args.substr(0, pos);
911  str2 = args.substr(pos + 1, args.length());
912  isValid = true;
913  }
914  }
915  return isValid;
916 }
917 
918 uint32_t parseNumber(const std::string &str)
919 {
920  uint32_t i = 0;
921  int idx = 0;
922  if (strStartWith(str, "0x"))
923  idx = 2;
924  else if (str[0] == 'h' || str[0] == 'x')
925  idx = 1;
926  if (idx > 0)
927  sscanf(str.substr(idx).c_str(), "%10x", &i);
928  else
929  i = atoi(str.c_str());
930  return i;
931 }
932 
933 std::string removeToken(std::string &str,
934  const std::string &token)
935 {
936  const size_t idx = str.find(token);
937  if (idx > 0 && idx != std::string::npos)
938  str = str.substr(idx + 1);
939  else
940  str.clear();
941  return str;
942 }
943 
944 std::string timeToStr(const uint32_t time)
945 {
946  char buf[101];
947  const time_t tempTime = time;
948  tm *const timeInfo = localtime(&tempTime);
949  if (strftime(&buf[0], 100, "%Y-%m-%d_%H-%M-%S", timeInfo) != 0U)
950  return std::string(buf);
951  return "unknown";
952 }
953 
954 std::string timeDiffToString(int timeDiff)
955 {
956  std::string str;
957 
958  const int weeks = timeDiff / 60 / 60 / 24 / 7;
959  if (weeks > 0)
960  {
961  // TRANSLATORS: uptime command
962  str = strprintf(ngettext(N_("%d week"), N_("%d weeks"),
963  weeks), weeks);
964  timeDiff -= weeks * 60 * 60 * 24 * 7;
965  }
966 
967  const int days = timeDiff / 60 / 60 / 24;
968  if (days > 0)
969  {
970  if (!str.empty())
971  str.append(", ");
972  // TRANSLATORS: uptime command
973  str.append(strprintf(ngettext(N_("%d day"), N_("%d days"),
974  days), days));
975  timeDiff -= days * 60 * 60 * 24;
976  }
977  const int hours = timeDiff / 60 / 60;
978  if (hours > 0)
979  {
980  if (!str.empty())
981  str.append(", ");
982  // TRANSLATORS: uptime command
983  str.append(strprintf(ngettext(N_("%d hour"), N_("%d hours"),
984  hours), hours));
985  timeDiff -= hours * 60 * 60;
986  }
987  const int min = timeDiff / 60;
988  if (min > 0)
989  {
990  if (!str.empty())
991  str.append(", ");
992  // TRANSLATORS: uptime command
993  str.append(strprintf(ngettext(N_("%d minute"), N_("%d minutes"),
994  min), min));
995  timeDiff -= min * 60;
996  }
997 
998  if (timeDiff > 0)
999  {
1000  if (!str.empty())
1001  str.append(", ");
1002  // TRANSLATORS: uptime command
1003  str.append(strprintf(ngettext(N_("%d second"), N_("%d seconds"),
1004  timeDiff), timeDiff));
1005  }
1006  if (str.empty())
1007  {
1008  // TRANSLATORS: uptime command
1009  str.append(strprintf(ngettext(N_("%d second"), N_("%d seconds"),
1010  0), 0));
1011  }
1012  return str;
1013 }
1014 
1015 std::string escapeString(std::string str)
1016 {
1017  replaceAll(str, "\"", "\\\"");
1018  return "\"" + str + "\"";
1019 }
1020 
1021 void sanitizePath(std::string &path)
1022 {
1023 #ifdef WIN32
1024  const char sepStr = '\\';
1025  const std::string sep2Str = "\\\\";
1026  const std::string sepWrongStr = "/";
1027 #else
1028  const char sepStr = '/';
1029  const std::string sep2Str = "//";
1030  const std::string sepWrongStr = "\\";
1031 #endif
1032  replaceRecursiveAll(path, sepWrongStr, sepStr);
1033  replaceRecursiveAll(path, sep2Str, sepStr);
1034 }
1035 
1036 std::string pathJoin(std::string str1,
1037  const std::string &str2)
1038 {
1039 #ifdef WIN32
1040  const char sep = '\\';
1041  std::string sepStr = "\\";
1042 #else
1043  const char sep = '/';
1044  std::string sepStr = "/";
1045 #endif
1046 
1047  if (str1.empty())
1048  {
1049  if (str2[0] == sep)
1050  return str2;
1051  return sepStr.append(str2);
1052  }
1053  const size_t sz1 = str1.size();
1054  if (str2.empty())
1055  {
1056  if (str1[sz1 - 1] == sep)
1057  return str1;
1058  return str1.append(sepStr);
1059  }
1060  if (str1[sz1 - 1] == sep)
1061  {
1062  if (str2[0] == sep)
1063  return str1.append(str2.substr(1));
1064  return str1.append(str2);
1065  }
1066  else
1067  {
1068  if (str2[0] == sep)
1069  return str1.append(str2);
1070  return str1.append(sepStr).append(str2);
1071  }
1072 }
1073 
1074 std::string pathJoin(std::string str1,
1075  const std::string &str2,
1076  const std::string &str3)
1077 {
1078 #ifdef WIN32
1079  const char sep = '\\';
1080  std::string sepStr = "\\";
1081 #else
1082  const char sep = '/';
1083  std::string sepStr = "/";
1084 #endif
1085 
1086  if (str1.empty())
1087  {
1088  return pathJoin(str2, str3);
1089  }
1090  size_t sz1 = str1.size();
1091  if (str2.empty())
1092  {
1093  return pathJoin(str1, str3);
1094  }
1095  if (str3.empty())
1096  {
1097  return pathJoin(str1, str2);
1098  }
1099  if (str1[sz1 - 1] == sep)
1100  {
1101  if (str2[0] == sep)
1102  str1.append(str2.substr(1));
1103  else
1104  str1.append(str2);
1105  }
1106  else
1107  {
1108  if (str2[0] == sep)
1109  str1.append(str2);
1110  else
1111  str1.append(sepStr).append(str2);
1112  }
1113 
1114  sz1 = str1.size();
1115  if (str1[sz1 - 1] == sep)
1116  {
1117  if (str3[0] == sep)
1118  return str1.append(str3.substr(1));
1119  return str1.append(str3);
1120  }
1121  else
1122  {
1123  if (str3[0] == sep)
1124  return str1.append(str3);
1125  return str1.append(sepStr).append(str3);
1126  }
1127 }
1128 
1129 std::string urlJoin(std::string str1,
1130  const std::string &str2)
1131 {
1132  const char sep = '/';
1133  std::string sepStr = "/";
1134 
1135  if (str1.empty())
1136  {
1137  if (str2[0] == sep)
1138  return str2;
1139  return sepStr.append(str2);
1140  }
1141  const size_t sz1 = str1.size();
1142  if (str2.empty())
1143  {
1144  if (str1[sz1 - 1] == sep)
1145  return str1;
1146  return str1.append(sepStr);
1147  }
1148  if (str1[sz1 - 1] == sep)
1149  {
1150  if (str2[0] == sep)
1151  return str1.append(str2.substr(1));
1152  return str1.append(str2);
1153  }
1154  else
1155  {
1156  if (str2[0] == sep)
1157  return str1.append(str2);
1158  return str1.append(sepStr).append(str2);
1159  }
1160 }
1161 
1162 size_t rfindSepatator(const std::string &str1)
1163 {
1164  const size_t idx1 = str1.rfind('/');
1165  const size_t idx2 = str1.rfind('\\');
1166  if (idx1 != std::string::npos)
1167  { // idx1
1168  if (idx2 != std::string::npos)
1169  { // idx1, idx2
1170  if (idx1 >= idx2)
1171  return idx1;
1172  else
1173  return idx2;
1174  }
1175  else
1176  { // idx1, not idx2
1177  return idx1;
1178  }
1179  }
1180  else
1181  { // not idx1
1182  if (idx2 != std::string::npos)
1183  { // not idx1, idx2
1184  return idx2;
1185  }
1186  else
1187  { // not idx1, not idx2
1188  return std::string::npos;
1189  }
1190  }
1191 }
1192 
1193 #ifndef DYECMD
1194 void replaceItemLinks(std::string &msg)
1195 {
1196  // Check for item link
1197  size_t start2 = msg.find('[');
1198  size_t sz = msg.size();
1199  while (start2 + 1 < sz &&
1200  start2 != std::string::npos &&
1201  msg[start2 + 1] != '@')
1202  {
1203  const size_t end = msg.find(']', start2);
1204  if (start2 + 1 != end &&
1205  end != std::string::npos)
1206  {
1207  // Catch multiple embeds and ignore them
1208  // so it doesn't crash the client.
1209  while ((msg.find('[', start2 + 1) != std::string::npos) &&
1210  (msg.find('[', start2 + 1) < end))
1211  {
1212  start2 = msg.find('[', start2 + 1);
1213  }
1214 
1215  if (start2 + 1 < sz &&
1216  end < sz &&
1217  end > start2 + 1)
1218  {
1219  std::string itemStr = msg.substr(start2 + 1, end - start2 - 1);
1220 
1221  StringVect parts;
1222  splitToStringVector(parts, itemStr, ',');
1223  if (parts.empty())
1224  return;
1225 
1226  const ItemInfo &itemInfo = ItemDB::get(parts[0]);
1227  const int itemId = itemInfo.getId();
1228  if (itemId != 0)
1229  {
1230  std::string temp = strprintf("@@%d", itemId);
1231  std::string name = parts[0];
1232  msg.erase(start2 + 1, end - start2 - 1);
1233  parts.erase(parts.begin());
1234  if (!parts.empty())
1235  name.clear();
1236 
1237  FOR_EACH (StringVectCIter, it, parts)
1238  {
1239  std:: string str = *it;
1240  trim(str);
1241  const ItemInfo &itemInfo2 = ItemDB::get(str);
1242  const int cardId = itemInfo2.getId();
1243  if (cardId != 0)
1244  temp.append(strprintf(",%d", cardId));
1245  }
1246  temp.append("|");
1247  temp.append(name);
1248  temp.append("@@");
1249  msg.insert(start2 + 1, temp);
1250  sz = msg.size();
1251  }
1252  }
1253  }
1254  start2 = msg.find('[', start2 + 1);
1255  }
1256 }
1257 #else // DYECMD
1258 
1259 void replaceItemLinks(std::string &msg A_UNUSED)
1260 {
1261 }
1262 #endif // DYECMD
parseBoolean
signed char parseBoolean(const std::string &value)
Definition: stringutils.cpp:754
anonymous_namespace{stringutils.cpp}::base
unsigned int base
Definition: stringutils.cpp:226
sanitizePath
void sanitizePath(std::string &path)
Definition: stringutils.cpp:1021
toStringPrint
std::string toStringPrint(const unsigned int val)
Definition: stringutils.cpp:776
stringToHexPath
std::string stringToHexPath(const std::string &str)
Definition: stringutils.cpp:609
splitToStringList
std::list< std::string > splitToStringList(const std::string &text, const char separator)
Definition: stringutils.cpp:472
splitToStringSet
void splitToStringSet(std::set< std::string > &tokens, const std::string &text, const char separator)
Definition: stringutils.cpp:498
encodeLinkText
std::string encodeLinkText(std::string data)
Definition: stringutils.cpp:766
cast.h
CAST_SIZE
#define CAST_SIZE
Definition: cast.h:33
anonymous_namespace{stringutils.cpp}::start
unsigned int start
Definition: stringutils.cpp:227
itemdb.h
removeSpriteIndex
std::string removeSpriteIndex(std::string str)
Definition: stringutils.cpp:284
findFirst
bool findFirst(const std::string &str1, const std::string &str2)
Definition: stringutils.cpp:651
combineDye3
std::string combineDye3(std::string file, const std::string &dye)
Definition: stringutils.cpp:562
replaceItemLinks
void replaceItemLinks(std::string &msg)
Definition: stringutils.cpp:1194
removeColors
std::string removeColors(std::string msg)
Definition: stringutils.cpp:121
Actions::msg
bool msg(InputEvent &event)
Definition: chat.cpp:38
splitToStringVector
void splitToStringVector(StringVect &tokens, const std::string &text, const char separator)
Definition: stringutils.cpp:484
CAST_8
#define CAST_8
Definition: cast.h:24
parseNumber
uint32_t parseNumber(const std::string &str)
Definition: stringutils.cpp:918
StringVect
std::vector< std::string > StringVect
Definition: stringvector.h:28
parse2Str
bool parse2Str(const std::string &args, std::string &str1, std::string &str2)
Definition: stringutils.cpp:898
removeToken
std::string removeToken(std::string &str, const std::string &token)
Definition: stringutils.cpp:933
A_UNUSED
#define A_UNUSED
Definition: localconsts.h:159
CAST_U32
#define CAST_U32
Definition: cast.h:30
parse2Int
bool parse2Int(const std::string &args, int &x, int &y)
Definition: stringutils.cpp:878
rfindSepatator
size_t rfindSepatator(const std::string &str1)
Definition: stringutils.cpp:1162
secureChatCommand
void secureChatCommand(std::string &str)
Definition: stringutils.cpp:872
pathJoin
std::string pathJoin(std::string str1, const std::string &str2)
Definition: stringutils.cpp:1036
iteminfo.h
findLast
bool findLast(const std::string &str1, const std::string &str2)
Definition: stringutils.cpp:639
replaceRecursiveAll
void replaceRecursiveAll(std::string &context, const std::string &from, const char to)
Definition: stringutils.cpp:385
trim
std::string & trim(std::string &str)
Definition: stringutils.cpp:46
getSafeUtf8String
const char * getSafeUtf8String(const std::string &text)
Definition: stringutils.cpp:307
normalize
std::string normalize(const std::string &name)
Definition: stringutils.cpp:444
findCutLast
bool findCutLast(std::string &str1, const std::string &str2)
Definition: stringutils.cpp:663
replaceAll
std::string & replaceAll(std::string &context, const std::string &from, const std::string &to)
Definition: stringutils.cpp:367
compareStrI
int compareStrI(const std::string &a, const std::string &b)
Definition: stringutils.cpp:134
cutLast
void cutLast(std::string &str1, const std::string &str2)
Definition: stringutils.cpp:678
CAST_U8
#define CAST_U8
Definition: cast.h:26
findSameSubstring
const std::string findSameSubstring(const std::string &str1, const std::string &str2)
Definition: stringutils.cpp:157
combineDye
std::string combineDye(std::string file, const std::string &dye)
Definition: stringutils.cpp:526
ipToString
const char * ipToString(const uint32_t address)
Definition: stringutils.cpp:85
replaceSpecialChars
void replaceSpecialChars(std::string &text)
Definition: stringutils.cpp:411
urlJoin
std::string urlJoin(std::string str1, const std::string &str2)
Definition: stringutils.cpp:1129
cutFirst
void cutFirst(std::string &str1, const std::string &str2)
Definition: stringutils.cpp:704
strprintf
std::string strprintf(const char *const format,...)
Definition: stringutils.cpp:99
CAST_S8
#define CAST_S8
Definition: cast.h:25
data
uint32_t data
Definition: maptypeproperty2.h:3
deleteCharLeft
void deleteCharLeft(std::string &str, unsigned *const pos)
Definition: stringutils.cpp:623
ItemInfo
Definition: iteminfo.h:52
findSameSubstringI
const std::string findSameSubstringI(const std::string &s1, const std::string &s2)
Definition: stringutils.cpp:170
gettext.h
x
x
Definition: graphics_calcImageRect.hpp:72
isDigit
bool isDigit(const std::string &str)
Definition: stringutils.cpp:858
timeToStr
std::string timeToStr(const uint32_t time)
Definition: stringutils.cpp:944
unpackList
std::list< std::string > unpackList(const std::string &str)
Definition: stringutils.cpp:604
toString
std::string toString(uint32_t num)
Definition: stringutils.cpp:784
stringutils.h
UTF8_MAX_SIZE
static const size_t UTF8_MAX_SIZE
Definition: utf8.h:26
getDateString
std::string getDateString()
Definition: stringutils.cpp:732
splitToIntList
std::list< int > splitToIntList(const std::string &text, const char separator)
Definition: stringutils.cpp:460
getFileName
std::string getFileName(const std::string &path)
Definition: stringutils.cpp:337
utf8.h
atox
unsigned int atox(const std::string &str)
Definition: stringutils.cpp:77
foreach.h
EmoteDB::size
int size()
Definition: emotedb.cpp:305
decodeStr
unsigned int decodeStr(const std::string &str)
Definition: stringutils.cpp:247
toUpper
std::string & toUpper(std::string &str)
Definition: stringutils.cpp:71
getDateTimeString
std::string getDateTimeString()
Definition: stringutils.cpp:743
escapeString
std::string escapeString(std::string str)
Definition: stringutils.cpp:1015
packList
std::string packList(const std::list< std::string > &list)
Definition: stringutils.cpp:589
getBoolFromString
bool getBoolFromString(const std::string &text)
Definition: stringutils.cpp:399
restrict
#define restrict
Definition: localconsts.h:164
timeDiffToString
std::string timeDiffToString(int timeDiff)
Definition: stringutils.cpp:954
findAny
size_t findAny(const std::string &text, const std::string &chars, const size_t pos)
Definition: stringutils.cpp:209
StringVectCIter
StringVect::const_iterator StringVectCIter
Definition: stringvector.h:30
CAST_S32
#define CAST_S32
Definition: cast.h:29
ItemInfo::getId
int getId() const
Definition: iteminfo.h:67
toLower
std::string & toLower(std::string &str)
Definition: stringutils.cpp:65
ItemDB::get
const ItemInfo & get(const int id)
Definition: itemdb.cpp:792
strStartWith
bool strStartWith(const std::string &str1, const std::string &str2)
Definition: stringutils.cpp:723
splitToIntVector
void splitToIntVector(std::vector< int > &tokens, const std::string &text, const char separator)
Definition: stringutils.cpp:512
extractNameFromSprite
std::string extractNameFromSprite(std::string str)
Definition: stringutils.cpp:262
findCutFirst
bool findCutFirst(std::string &str1, const std::string &str2)
Definition: stringutils.cpp:689
y
y
Definition: graphics_calcImageRect.hpp:72
removeProtocol
std::string & removeProtocol(std::string &url)
Definition: stringutils.cpp:715
N_
#define N_(s)
Definition: gettext.h:35
findI
size_t findI(std::string str, std::string subStr)
Definition: stringutils.cpp:188
combineDye2
std::string combineDye2(std::string file, const std::string &dye)
Definition: stringutils.cpp:537
splitToIntSet
void splitToIntSet(std::set< int > &tokens, const std::string &text, const char separator)
Definition: stringutils.cpp:450
FOR_EACH
#define FOR_EACH(type, iter, array)
Definition: foreach.h:24
debug.h
decodeLinkText
std::string decodeLinkText(std::string data)
Definition: stringutils.cpp:771
encodeStr
const std::string encodeStr(unsigned int value, const unsigned int size)
Definition: stringutils.cpp:230
Actions::url
bool url(InputEvent &event)
Definition: commands.cpp:63
Actions::itemInfo
bool itemInfo(InputEvent &event)
Definition: commands.cpp:104
getFileDir
std::string getFileDir(const std::string &path)
Definition: stringutils.cpp:352