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-2018 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 (unsigned int 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  pos1 = pos2;
343  else if (pos2 != std::string::npos && pos2 > pos1)
344  pos1 = pos2;
345 
346  if (pos1 == std::string::npos)
347  return path;
348  return path.substr(pos1 + 1);
349 }
350 
351 std::string getFileDir(const std::string &path)
352 {
353  size_t pos1 = path.rfind('/');
354  const size_t pos2 = path.rfind('\\');
355  if (pos1 == std::string::npos)
356  pos1 = pos2;
357  else if (pos2 != std::string::npos && pos2 > pos1)
358  pos1 = pos2;
359 
360  if (pos1 == std::string::npos)
361  return path;
362  return path.substr(0, pos1);
363 }
364 
365 std::string& replaceAll(std::string& context,
366  const std::string &restrict from,
367  const std::string &restrict to)
368 {
369  if (from.empty())
370  return context;
371  size_t lookHere = 0;
372  size_t foundHere;
373  const size_t fromSize = from.size();
374  const size_t toSize = to.size();
375  while ((foundHere = context.find(from, lookHere)) != std::string::npos)
376  {
377  context.replace(foundHere, fromSize, to);
378  lookHere = foundHere + toSize;
379  }
380  return context;
381 }
382 
383 void replaceRecursiveAll(std::string& context,
384  const std::string &restrict from,
385  const char to)
386 {
387  size_t lookHere = 0;
388  size_t foundHere;
389  const size_t fromSize = from.size();
390  while ((foundHere = context.find(from, lookHere)) != std::string::npos)
391  {
392  context.replace(foundHere, fromSize, 1, to);
393  lookHere = foundHere;
394  }
395 }
396 
397 bool getBoolFromString(const std::string &text)
398 {
399  std::string txt = text;
400  toLower(trim(txt));
401  if (txt == "true" || txt == "yes" || txt == "on" || txt == "1")
402  return true;
403  else if (txt == "false" || txt == "no" || txt == "off" || txt == "0")
404  return false;
405  else
406  return static_cast<bool>(atoi(txt.c_str()));
407 }
408 
409 void replaceSpecialChars(std::string &text)
410 {
411  size_t pos1 = text.find('&');
412  while (pos1 != std::string::npos)
413  {
414  const size_t idx = pos1 + 1;
415  const size_t sz = text.size();
416  if (idx >= sz)
417  break;
418 
419  size_t f;
420  for (f = idx; f < sz; f ++)
421  {
422  if (text[f] < '0' || text[f] > '9')
423  break;
424  }
425  if (idx + 1 < f && text[f] == ';')
426  {
427  std::string str(" ");
428  str[0] = CAST_S8(atoi(text.substr(
429  idx, f - idx).c_str()));
430  text = text.substr(0, pos1).append(str).append(text.substr(f + 1));
431  pos1 += 1;
432  }
433  else
434  {
435  pos1 = f + 1;
436  }
437 
438  pos1 = text.find('&', pos1);
439  }
440 }
441 
442 std::string normalize(const std::string &name)
443 {
444  std::string normalized = name;
445  return toLower(trim(normalized));
446 }
447 
448 void splitToIntSet(std::set<int> &tokens,
449  const std::string &text,
450  const char separator)
451 {
452  std::stringstream ss(text);
453  std::string item;
454  while (std::getline(ss, item, separator))
455  tokens.insert(atoi(item.c_str()));
456 }
457 
458 std::list<int> splitToIntList(const std::string &text,
459  const char separator)
460 {
461  std::list<int> tokens;
462  std::stringstream ss(text);
463  std::string item;
464  while (std::getline(ss, item, separator))
465  tokens.push_back(atoi(item.c_str()));
466 
467  return tokens;
468 }
469 
470 std::list<std::string> splitToStringList(const std::string &text,
471  const char separator)
472 {
473  std::list<std::string> tokens;
474  std::stringstream ss(text);
475  std::string item;
476  while (std::getline(ss, item, separator))
477  tokens.push_back(item);
478 
479  return tokens;
480 }
481 
483  const std::string &text,
484  const char separator)
485 {
486  std::stringstream ss(text);
487  std::string item;
488  while (std::getline(ss, item, separator))
489  {
490  item = trim(item);
491  if (!item.empty())
492  tokens.push_back(item);
493  }
494 }
495 
496 void splitToStringSet(std::set<std::string> &tokens,
497  const std::string &text,
498  const char separator)
499 {
500  std::stringstream ss(text);
501  std::string item;
502  while (std::getline(ss, item, separator))
503  {
504  item = trim(item);
505  if (!item.empty())
506  tokens.insert(item);
507  }
508 }
509 
510 void splitToIntVector(STD_VECTOR<int> &tokens,
511  const std::string &text,
512  const char separator)
513 {
514  std::stringstream ss(text);
515  std::string item;
516  while (std::getline(ss, item, separator))
517  {
518  item = trim(item);
519  if (!item.empty())
520  tokens.push_back(atoi(item.c_str()));
521  }
522 }
523 
524 std::string combineDye(std::string file,
525  const std::string &dye)
526 {
527  if (dye.empty())
528  return file;
529  const size_t pos = file.find_last_of('|');
530  if (pos != std::string::npos)
531  return file.substr(0, pos).append("|").append(dye);
532  return file.append("|").append(dye);
533 }
534 
535 std::string combineDye2(std::string file,
536  const std::string &dye)
537 {
538  if (dye.empty())
539  return file;
540 
541  const size_t pos = file.find_last_of('|');
542  if (pos != std::string::npos)
543  {
544  const std::string dye1 = file.substr(pos + 1);
545  std::string str;
546  file = file.substr(0, pos);
547  const std::list<std::string> list1 = splitToStringList(dye1, ';');
548  const std::list<std::string> list2 = splitToStringList(dye, ';');
549  for (std::list<std::string>::const_iterator it1 = list1.begin(),
550  it2 = list2.begin(), it1_end = list1.end(), it2_end = list2.end();
551  it1 != it1_end && it2 != it2_end; ++it1, ++it2)
552  {
553  str.append(*it1).append(":").append(*it2).append(";");
554  }
555  return file.append("|").append(str);
556  }
557  return file;
558 }
559 
560 std::string combineDye3(std::string file,
561  const std::string &dye)
562 {
563  if (dye.empty())
564  return file;
565 
566  const size_t pos = file.find_last_of('|');
567  if (pos != std::string::npos)
568  {
569  const std::string dye1 = file.substr(pos + 1);
570  std::string str;
571  file = file.substr(0, pos);
572  const std::list<std::string> list1 = splitToStringList(dye1, ';');
573  const std::list<std::string> list2 = splitToStringList(dye, ';');
574  for (std::list<std::string>::const_iterator it1 = list1.begin(),
575  it2 = list2.begin(), it1_end = list1.end(), it2_end = list2.end();
576  it1 != it1_end && it2 != it2_end; ++it1, ++it2)
577  {
578  str.append(*it1).append(":").append(*it2).append(";");
579  }
580  return file.append("|").append(str);
581  }
582  if (file.empty())
583  return file;
584  return file.append("|").append(dye);
585 }
586 
587 std::string packList(const std::list<std::string> &list)
588 {
589  std::list<std::string>::const_iterator i = list.begin();
590  std::string str;
591  while (i != list.end())
592  {
593  str.append(*i).append("|");
594  ++ i;
595  }
596  const size_t sz = str.size();
597  if (sz > 1)
598  str = str.substr(0, sz - 1);
599  return str;
600 }
601 
602 std::list<std::string> unpackList(const std::string &str)
603 {
604  return splitToStringList(str, '|');
605 }
606 
607 std::string stringToHexPath(const std::string &str)
608 {
609  if (str.empty())
610  return "";
611 
612  std::string hex = strprintf("%%%2x/", CAST_U32(str[0]));
613  for (unsigned f = 1, fsz = CAST_U32(str.size());
614  f < fsz; f ++)
615  {
616  hex.append(strprintf("%%%2x", CAST_U32(str[f])));
617  }
618  return hex;
619 }
620 
621 void deleteCharLeft(std::string &str,
622  unsigned *const pos)
623 {
624  if (pos == nullptr)
625  return;
626 
627  while (*pos > 0)
628  {
629  (*pos)--;
630  const int v = str[*pos];
631  str.erase(*pos, 1);
632  if ((v & 192) != 128)
633  break;
634  }
635 }
636 
637 bool findLast(const std::string &restrict str1,
638  const std::string &restrict str2)
639 {
640  const size_t s1 = str1.size();
641  const size_t s2 = str2.size();
642  if (s1 < s2)
643  return false;
644  if (str1.substr(s1 - s2) == str2)
645  return true;
646  return false;
647 }
648 
649 bool findFirst(const std::string &restrict str1,
650  const std::string &restrict str2)
651 {
652  const size_t s1 = str1.size();
653  const size_t s2 = str2.size();
654  if (s1 < s2)
655  return false;
656  if (str1.substr(0, s2) == str2)
657  return true;
658  return false;
659 }
660 
661 bool findCutLast(std::string &restrict str1,
662  const std::string &restrict str2)
663 {
664  const size_t s1 = str1.size();
665  const size_t s2 = str2.size();
666  if (s1 < s2)
667  return false;
668  if (str1.substr(s1 - s2) == str2)
669  {
670  str1 = str1.substr(0, s1 - s2);
671  return true;
672  }
673  return false;
674 }
675 
676 void cutLast(std::string &restrict str1,
677  const std::string &restrict str2)
678 {
679  const size_t s1 = str1.size();
680  const size_t s2 = str2.size();
681  if (s1 < s2)
682  return;
683  if (str1.substr(s1 - s2) == str2)
684  str1 = str1.substr(0, s1 - s2);
685 }
686 
687 bool findCutFirst(std::string &restrict str1,
688  const std::string &restrict str2)
689 {
690  const size_t s1 = str1.size();
691  const size_t s2 = str2.size();
692  if (s1 < s2)
693  return false;
694  if (str1.substr(0, s2) == str2)
695  {
696  str1 = str1.substr(s2);
697  return true;
698  }
699  return false;
700 }
701 
702 void cutFirst(std::string &restrict str1,
703  const std::string &restrict str2)
704 {
705  const size_t s1 = str1.size();
706  const size_t s2 = str2.size();
707  if (s1 < s2)
708  return;
709  if (str1.substr(0, s2) == str2)
710  str1 = str1.substr(s2);
711 }
712 
713 std::string &removeProtocol(std::string &url)
714 {
715  const size_t i = url.find("://");
716  if (i != std::string::npos)
717  url = url.substr(i + 3);
718  return url;
719 }
720 
721 bool strStartWith(const std::string &restrict str1,
722  const std::string &restrict str2)
723 {
724  const size_t sz2 = str2.size();
725  if (str1.size() < sz2)
726  return false;
727  return str1.substr(0, sz2) == str2;
728 }
729 
730 std::string getDateString()
731 {
732  char buffer[80];
733  time_t rawtime;
734  time(&rawtime);
735  const tm *const timeinfo = localtime(&rawtime);
736 
737  strftime(buffer, 79, "%Y-%m-%d", timeinfo);
738  return std::string(buffer);
739 }
740 
741 std::string getDateTimeString()
742 {
743  char buffer[80];
744  time_t rawtime;
745  time(&rawtime);
746  const tm *const timeinfo = localtime(&rawtime);
747 
748  strftime(buffer, 79, "%Y-%m-%d %H:%M:%S", timeinfo);
749  return std::string(buffer);
750 }
751 
752 signed char parseBoolean(const std::string &value)
753 {
754  std::string txt = value;
755  toLower(trim(txt));
756  if (txt == "true" || txt == "yes" || txt == "on" || txt == "1")
757  return 1;
758  else if (txt == "false" || txt == "no" || txt == "off" || txt == "0")
759  return 0;
760  else
761  return -1;
762 }
763 
764 std::string encodeLinkText(std::string data)
765 {
766  return replaceAll(data, "|", "\342\235\230");
767 }
768 
769 std::string decodeLinkText(std::string data)
770 {
771  return replaceAll(data, "\342\235\230", "|");
772 }
773 
774 std::string toStringPrint(const unsigned int val)
775 {
776  static char str[100];
777  snprintf(str, sizeof(str), "%u 0x%x", val, val);
778  str[99] = 0;
779  return str;
780 }
781 
782 std::string toString(uint32_t num)
783 {
784  char buf[30];
785  buf[29] = '\0';
786  size_t idx = 28;
787  do
788  buf[idx--] = CAST_8((num % 10) + '0');
789  while ((num /= 10) != 0);
790  return buf + idx + 1;
791 }
792 
793 std::string toString(uint64_t num)
794 {
795  char buf[100];
796  buf[99] = '\0';
797  size_t idx = 98;
798  do
799  buf[idx--] = CAST_8((num % 10) + '0');
800  while ((num /= 10) != 0);
801  return buf + idx + 1;
802 }
803 
804 std::string toString(uint16_t num)
805 {
806  char buf[10];
807  buf[9] = '\0';
808  size_t idx = 8;
809  do
810  buf[idx--] = CAST_8((num % 10) + '0');
811  while ((num /= 10) != 0);
812  return buf + idx + 1;
813 }
814 
815 std::string toString(unsigned char num)
816 {
817  char buf[5];
818  buf[4] = '\0';
819  size_t idx = 3;
820  do
821  buf[idx--] = CAST_8((num % 10) + '0');
822  while ((num /= 10) != 0);
823  return buf + idx + 1;
824 }
825 
826 std::string toString(int32_t num)
827 {
828  char buf[30];
829  bool useSign(false);
830  buf[29] = '\0';
831  size_t idx = 28;
832 
833  if (num < 0)
834  {
835  useSign = true;
836  num = -num;
837  }
838  do
839  buf[idx--] = CAST_8((num % 10) + '0');
840  while ((num /= 10) != 0);
841  if (useSign)
842  buf[idx--] = '-';
843  return buf + idx + 1;
844 }
845 
846 std::string toString(const float num)
847 {
848  return strprintf("%f", num);
849 }
850 
851 std::string toString(const double num)
852 {
853  return strprintf("%f", static_cast<float>(num));
854 }
855 
856 bool isDigit(const std::string &str)
857 {
858  if (str.empty())
859  return false;
860  const size_t sz = str.size();
861  for (size_t f = 0; f < sz; f ++)
862  {
863  const char &chr = str[f];
864  if (chr < '0' || chr > '9')
865  return false;
866  }
867  return true;
868 }
869 
870 void secureChatCommand(std::string &str)
871 {
872  if (str[0] == '/' || str[0] == '@' || str[0] == '#')
873  str = "_" + str;
874 }
875 
876 bool parse2Int(const std::string &args,
877  int &x,
878  int &y)
879 {
880  bool isValid = false;
881  size_t pos = args.find(' ');
882  if (pos == std::string::npos)
883  pos = args.find(',');
884  if (pos != std::string::npos)
885  {
886  if (pos + 1 < args.length())
887  {
888  x = atoi(args.substr(0, pos).c_str());
889  y = atoi(args.substr(pos + 1, args.length()).c_str());
890  isValid = true;
891  }
892  }
893  return isValid;
894 }
895 
896 bool parse2Str(const std::string &args,
897  std::string &str1,
898  std::string &str2)
899 {
900  bool isValid = false;
901  size_t pos = args.find(' ');
902  if (pos == std::string::npos)
903  pos = args.find(',');
904  if (pos != std::string::npos)
905  {
906  if (pos + 1 < args.length())
907  {
908  str1 = args.substr(0, pos);
909  str2 = args.substr(pos + 1, args.length());
910  isValid = true;
911  }
912  }
913  return isValid;
914 }
915 
916 uint32_t parseNumber(const std::string &str)
917 {
918  uint32_t i = 0;
919  int idx = 0;
920  if (strStartWith(str, "0x"))
921  idx = 2;
922  else if (str[0] == 'h' || str[0] == 'x')
923  idx = 1;
924  if (idx > 0)
925  sscanf(str.substr(idx).c_str(), "%10x", &i);
926  else
927  i = atoi(str.c_str());
928  return i;
929 }
930 
931 std::string removeToken(std::string &str,
932  const std::string &token)
933 {
934  const size_t idx = str.find(token);
935  if (idx > 0 && idx != std::string::npos)
936  str = str.substr(idx + 1);
937  else
938  str.clear();
939  return str;
940 }
941 
942 std::string timeToStr(const uint32_t time)
943 {
944  char buf[101];
945  const time_t tempTime = time;
946  tm *const timeInfo = localtime(&tempTime);
947  if (strftime(&buf[0], 100, "%Y-%m-%d_%H-%M-%S", timeInfo) != 0u)
948  return std::string(buf);
949  return "unknown";
950 }
951 
952 std::string timeDiffToString(int timeDiff)
953 {
954  std::string str;
955 
956  const int weeks = timeDiff / 60 / 60 / 24 / 7;
957  if (weeks > 0)
958  {
959  // TRANSLATORS: uptime command
960  str = strprintf(ngettext(N_("%d week"), N_("%d weeks"),
961  weeks), weeks);
962  timeDiff -= weeks * 60 * 60 * 24 * 7;
963  }
964 
965  const int days = timeDiff / 60 / 60 / 24;
966  if (days > 0)
967  {
968  if (!str.empty())
969  str.append(", ");
970  // TRANSLATORS: uptime command
971  str.append(strprintf(ngettext(N_("%d day"), N_("%d days"),
972  days), days));
973  timeDiff -= days * 60 * 60 * 24;
974  }
975  const int hours = timeDiff / 60 / 60;
976  if (hours > 0)
977  {
978  if (!str.empty())
979  str.append(", ");
980  // TRANSLATORS: uptime command
981  str.append(strprintf(ngettext(N_("%d hour"), N_("%d hours"),
982  hours), hours));
983  timeDiff -= hours * 60 * 60;
984  }
985  const int min = timeDiff / 60;
986  if (min > 0)
987  {
988  if (!str.empty())
989  str.append(", ");
990  // TRANSLATORS: uptime command
991  str.append(strprintf(ngettext(N_("%d minute"), N_("%d minutes"),
992  min), min));
993  timeDiff -= min * 60;
994  }
995 
996  if (timeDiff > 0)
997  {
998  if (!str.empty())
999  str.append(", ");
1000  // TRANSLATORS: uptime command
1001  str.append(strprintf(ngettext(N_("%d second"), N_("%d seconds"),
1002  timeDiff), timeDiff));
1003  }
1004  if (str.empty())
1005  {
1006  // TRANSLATORS: uptime command
1007  str.append(strprintf(ngettext(N_("%d second"), N_("%d seconds"),
1008  0), 0));
1009  }
1010  return str;
1011 }
1012 
1013 std::string escapeString(std::string str)
1014 {
1015  replaceAll(str, "\"", "\\\"");
1016  return "\"" + str + "\"";
1017 }
1018 
1019 void sanitizePath(std::string &path)
1020 {
1021 #ifdef WIN32
1022  const char sepStr = '\\';
1023  const std::string sep2Str = "\\\\";
1024  const std::string sepWrongStr = "/";
1025 #else
1026  const char sepStr = '/';
1027  const std::string sep2Str = "//";
1028  const std::string sepWrongStr = "\\";
1029 #endif
1030  replaceRecursiveAll(path, sepWrongStr, sepStr);
1031  replaceRecursiveAll(path, sep2Str, sepStr);
1032 }
1033 
1034 std::string pathJoin(std::string str1,
1035  const std::string &str2)
1036 {
1037 #ifdef WIN32
1038  const char sep = '\\';
1039  std::string sepStr = "\\";
1040 #else
1041  const char sep = '/';
1042  std::string sepStr = "/";
1043 #endif
1044 
1045  if (str1.empty())
1046  {
1047  if (str2[0] == sep)
1048  return str2;
1049  return sepStr.append(str2);
1050  }
1051  const size_t sz1 = str1.size();
1052  if (str2.empty())
1053  {
1054  if (str1[sz1 - 1] == sep)
1055  return str1;
1056  return str1.append(sepStr);
1057  }
1058  if (str1[sz1 - 1] == sep)
1059  {
1060  if (str2[0] == sep)
1061  return str1.append(str2.substr(1));
1062  return str1.append(str2);
1063  }
1064  else
1065  {
1066  if (str2[0] == sep)
1067  return str1.append(str2);
1068  return str1.append(sepStr).append(str2);
1069  }
1070 }
1071 
1072 std::string pathJoin(std::string str1,
1073  const std::string &str2,
1074  const std::string &str3)
1075 {
1076 #ifdef WIN32
1077  const char sep = '\\';
1078  std::string sepStr = "\\";
1079 #else
1080  const char sep = '/';
1081  std::string sepStr = "/";
1082 #endif
1083 
1084  if (str1.empty())
1085  {
1086  return pathJoin(str2, str3);
1087  }
1088  size_t sz1 = str1.size();
1089  if (str2.empty())
1090  {
1091  return pathJoin(str1, str3);
1092  }
1093  if (str3.empty())
1094  {
1095  return pathJoin(str1, str2);
1096  }
1097  if (str1[sz1 - 1] == sep)
1098  {
1099  if (str2[0] == sep)
1100  str1.append(str2.substr(1));
1101  else
1102  str1.append(str2);
1103  }
1104  else
1105  {
1106  if (str2[0] == sep)
1107  str1.append(str2);
1108  else
1109  str1.append(sepStr).append(str2);
1110  }
1111 
1112  sz1 = str1.size();
1113  if (str1[sz1 - 1] == sep)
1114  {
1115  if (str3[0] == sep)
1116  return str1.append(str3.substr(1));
1117  return str1.append(str3);
1118  }
1119  else
1120  {
1121  if (str3[0] == sep)
1122  return str1.append(str3);
1123  return str1.append(sepStr).append(str3);
1124  }
1125 }
1126 
1127 std::string urlJoin(std::string str1,
1128  const std::string &str2)
1129 {
1130  const char sep = '/';
1131  std::string sepStr = "/";
1132 
1133  if (str1.empty())
1134  {
1135  if (str2[0] == sep)
1136  return str2;
1137  return sepStr.append(str2);
1138  }
1139  const size_t sz1 = str1.size();
1140  if (str2.empty())
1141  {
1142  if (str1[sz1 - 1] == sep)
1143  return str1;
1144  return str1.append(sepStr);
1145  }
1146  if (str1[sz1 - 1] == sep)
1147  {
1148  if (str2[0] == sep)
1149  return str1.append(str2.substr(1));
1150  return str1.append(str2);
1151  }
1152  else
1153  {
1154  if (str2[0] == sep)
1155  return str1.append(str2);
1156  return str1.append(sepStr).append(str2);
1157  }
1158 }
1159 
1160 #ifndef DYECMD
1161 void replaceItemLinks(std::string &msg)
1162 {
1163  // Check for item link
1164  size_t start2 = msg.find('[');
1165  size_t sz = msg.size();
1166  while (start2 + 1 < sz &&
1167  start2 != std::string::npos &&
1168  msg[start2 + 1] != '@')
1169  {
1170  const size_t end = msg.find(']', start2);
1171  if (start2 + 1 != end &&
1172  end != std::string::npos)
1173  {
1174  // Catch multiple embeds and ignore them
1175  // so it doesn't crash the client.
1176  while ((msg.find('[', start2 + 1) != std::string::npos) &&
1177  (msg.find('[', start2 + 1) < end))
1178  {
1179  start2 = msg.find('[', start2 + 1);
1180  }
1181 
1182  if (start2 + 1 < sz &&
1183  end < sz &&
1184  end > start2 + 1)
1185  {
1186  std::string itemStr = msg.substr(start2 + 1, end - start2 - 1);
1187 
1188  StringVect parts;
1189  splitToStringVector(parts, itemStr, ',');
1190  if (parts.empty())
1191  return;
1192 
1193  const ItemInfo &itemInfo = ItemDB::get(parts[0]);
1194  const int itemId = itemInfo.getId();
1195  if (itemId != 0)
1196  {
1197  std::string temp = strprintf("@@%d", itemId);
1198  std::string name = parts[0];
1199  msg.erase(start2 + 1, end - start2 - 1);
1200  parts.erase(parts.begin());
1201  if (!parts.empty())
1202  name.clear();
1203 
1204  FOR_EACH (StringVectCIter, it, parts)
1205  {
1206  std:: string str = *it;
1207  trim(str);
1208  const ItemInfo &itemInfo2 = ItemDB::get(str);
1209  const int cardId = itemInfo2.getId();
1210  if (cardId != 0)
1211  temp.append(strprintf(",%d", cardId));
1212  }
1213  temp.append("|");
1214  temp.append(name);
1215  temp.append("@@");
1216  msg.insert(start2 + 1, temp);
1217  sz = msg.size();
1218  }
1219  }
1220  }
1221  start2 = msg.find('[', start2 + 1);
1222  }
1223 }
1224 #else // DYECMD
1225 
1226 void replaceItemLinks(std::string &msg A_UNUSED)
1227 {
1228 }
1229 #endif // DYECMD
std::string & toLower(std::string &str)
Definition: stringutils.cpp:65
#define CAST_U32
Definition: cast.h:30
#define FOR_EACH(type, iter, array)
Definition: foreach.h:24
bool strStartWith(const std::string &str1, const std::string &str2)
std::string decodeLinkText(std::string data)
std::string encodeLinkText(std::string data)
std::string removeSpriteIndex(std::string str)
const ItemInfo & get(const int id)
Definition: itemdb.cpp:792
signed char parseBoolean(const std::string &value)
#define CAST_U8
Definition: cast.h:26
StringVect::const_iterator StringVectCIter
Definition: stringvector.h:30
std::list< std::string > splitToStringList(const std::string &text, const char separator)
void splitToStringVector(StringVect &tokens, const std::string &text, const char separator)
std::string toStringPrint(const unsigned int val)
void splitToIntSet(std::set< int > &tokens, const std::string &text, const char separator)
std::string & removeProtocol(std::string &url)
std::string removeToken(std::string &str, const std::string &token)
void splitToStringSet(std::set< std::string > &tokens, const std::string &text, const char separator)
#define N_(s)
Definition: gettext.h:35
const std::string encodeStr(unsigned int value, const unsigned int size)
void replaceItemLinks(std::string &msg)
int getId() const
Definition: iteminfo.h:67
std::string combineDye3(std::string file, const std::string &dye)
void secureChatCommand(std::string &str)
std::string pathJoin(std::string str1, const std::string &str2)
std::string stringToHexPath(const std::string &str)
void sanitizePath(std::string &path)
bool parse2Str(const std::string &args, std::string &str1, std::string &str2)
std::string & trim(std::string &str)
Definition: stringutils.cpp:46
std::string & replaceAll(std::string &context, const std::string &from, const std::string &to)
bool msg(InputEvent &event)
Definition: chat.cpp:38
std::string removeColors(std::string msg)
static const size_t UTF8_MAX_SIZE
Definition: utf8.h:26
std::vector< std::string > StringVect
Definition: stringvector.h:28
void replaceRecursiveAll(std::string &context, const std::string &from, const char to)
std::string urlJoin(std::string str1, const std::string &str2)
uint32_t parseNumber(const std::string &str)
const char * getSafeUtf8String(const std::string &text)
bool findFirst(const std::string &str1, const std::string &str2)
int compareStrI(const std::string &a, const std::string &b)
bool findLast(const std::string &str1, const std::string &str2)
#define CAST_8
Definition: cast.h:24
const std::string findSameSubstringI(const std::string &s1, const std::string &s2)
std::string combineDye(std::string file, const std::string &dye)
#define CAST_S32
Definition: cast.h:29
bool findCutLast(std::string &str1, const std::string &str2)
std::string strprintf(const char *const format,...)
Definition: stringutils.cpp:99
bool parse2Int(const std::string &args, int &x, int &y)
void deleteCharLeft(std::string &str, unsigned *const pos)
const std::string findSameSubstring(const std::string &str1, const std::string &str2)
std::list< std::string > unpackList(const std::string &str)
uint32_t data
void replaceSpecialChars(std::string &text)
std::string getDateString()
std::string normalize(const std::string &name)
bool isDigit(const std::string &str)
void cutLast(std::string &str1, const std::string &str2)
#define CAST_S8
Definition: cast.h:25
const char * ipToString(const uint32_t address)
Definition: stringutils.cpp:85
void cutFirst(std::string &str1, const std::string &str2)
std::list< int > splitToIntList(const std::string &text, const char separator)
unsigned int atox(const std::string &str)
Definition: stringutils.cpp:77
std::string getFileName(const std::string &path)
unsigned int decodeStr(const std::string &str)
size_t findAny(const std::string &text, const std::string &chars, const size_t pos)
std::string packList(const std::list< std::string > &list)
#define A_UNUSED
Definition: localconsts.h:151
bool getBoolFromString(const std::string &text)
std::string timeToStr(const uint32_t time)
std::string toString(uint32_t num)
std::string & toUpper(std::string &str)
Definition: stringutils.cpp:71
std::string getDateTimeString()
#define restrict
Definition: localconsts.h:156
std::string combineDye2(std::string file, const std::string &dye)
#define CAST_SIZE
Definition: cast.h:33
std::string escapeString(std::string str)
void splitToIntVector(std::vector< int > &tokens, const std::string &text, const char separator)
bool findCutFirst(std::string &str1, const std::string &str2)
std::string extractNameFromSprite(std::string str)
bool url(InputEvent &event)
Definition: commands.cpp:63
size_t findI(std::string str, std::string subStr)
std::string getFileDir(const std::string &path)
bool itemInfo(InputEvent &event)
Definition: commands.cpp:104
std::string timeDiffToString(int timeDiff)