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