OregonCore  revision 3611e8a-git
Your Favourite TBC server
Util.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "Util.h"
19 
20 #include "utf8.h"
21 #ifdef USE_SFMT_FOR_RNG
22 #include "SFMT.h"
23 #else
24 #include "MersenneTwister.h"
25 #endif // USE_SFMT
26 #include <ace/TSS_T.h>
27 #include <ace/INET_Addr.h>
28 
29 #ifdef USE_SFMT_FOR_RNG
30 typedef ACE_TSS<SFMTRand> SFMTRandTSS;
31 static SFMTRandTSS sfmtRand;
32 
33 int32 irand (int32 min, int32 max)
34 {
35  return int32(sfmtRand->IRandom(min, max));
36 }
37 
38 uint32 urand (uint32 min, uint32 max)
39 {
40  return sfmtRand->URandom(min, max);
41 }
42 
43 float frand(float min, float max)
44 {
45  return float(sfmtRand->Random() * (max - min) + min);
46 }
47 
48 int32 rand32 ()
49 {
50  return int32(sfmtRand->BRandom());
51 }
52 
53 double rand_norm(void)
54 {
55  return sfmtRand->Random();
56 }
57 
58 double rand_chance (void)
59 {
60  return sfmtRand->Random() * 100.0;
61 }
62 #else
63 typedef ACE_TSS<MTRand> MTRandTSS;
64 static MTRandTSS mtRand;
65 
66 int32 irand (int32 min, int32 max)
67 {
68  return int32 (mtRand->randInt (max - min)) + min;
69 }
70 
72 {
73  return mtRand->randInt (max - min) + min;
74 }
75 
76 float frand (float min, float max)
77 {
78  return mtRand->randExc (max - min) + min;
79 }
80 
82 {
83  return mtRand->randInt ();
84 }
85 
86 double rand_norm(void)
87 {
88  return mtRand->randExc ();
89 }
90 
91 double rand_chance (void)
92 {
93  return mtRand->randExc (100.0);
94 }
95 #endif // USE_SFMT_FOR_RNG
96 
97 Tokens StrSplit(const std::string& src, const std::string& sep)
98 {
99  Tokens r;
100  std::string s;
101  for (std::string::const_iterator i = src.begin(); i != src.end(); i++)
102  {
103  if (sep.find(*i) != std::string::npos)
104  {
105  if (s.length()) r.push_back(s);
106  s = "";
107  }
108  else
109  s += *i;
110  }
111  if (s.length()) r.push_back(s);
112  return r;
113 }
114 
115 void stripLineInvisibleChars(std::string& str)
116 {
117  static std::string const invChars = " \t\7\n";
118 
119  size_t wpos = 0;
120 
121  bool space = false;
122  for (size_t pos = 0; pos < str.size(); ++pos)
123  {
124  if (invChars.find(str[pos]) != std::string::npos)
125  {
126  if (!space)
127  {
128  str[wpos++] = ' ';
129  space = true;
130  }
131  }
132  else
133  {
134  if (wpos != pos)
135  str[wpos++] = str[pos];
136  else
137  ++wpos;
138  space = false;
139  }
140  }
141 
142  if (wpos < str.size())
143  str.erase(wpos, str.size());
144  if (str.find("|TInterface") != std::string::npos)
145  str.clear();
146 }
147 
148 std::string secsToTimeString(uint32 timeInSecs, bool shortText, bool hoursOnly)
149 {
150  uint32 secs = timeInSecs % MINUTE;
151  uint32 minutes = timeInSecs % HOUR / MINUTE;
152  uint32 hours = timeInSecs % DAY / HOUR;
153  uint32 days = timeInSecs / DAY;
154 
155  std::ostringstream ss;
156  if (days)
157  ss << days << (shortText ? "d" : " Day(s) ");
158  if (hours || hoursOnly)
159  ss << hours << (shortText ? "h" : " Hour(s) ");
160  if (!hoursOnly)
161  {
162  if (minutes)
163  ss << minutes << (shortText ? "m" : " Minute(s) ");
164  if (secs || (!days && !hours && !minutes) )
165  ss << secs << (shortText ? "s" : " Second(s).");
166  }
167 
168  return ss.str();
169 }
170 
171 uint32 TimeStringToSecs(const std::string& timestring)
172 {
173  uint32 secs = 0;
174  uint32 buffer = 0;
175  uint32 multiplier = 0;
176 
177  for (std::string::const_iterator itr = timestring.begin(); itr != timestring.end(); itr++ )
178  {
179  if (isdigit(*itr))
180  {
181  std::string str; //very complicated typecast char->const char*; is there no better way?
182  str += *itr;
183  const char* tmp = str.c_str();
184 
185  buffer *= 10;
186  buffer += atoi(tmp);
187  }
188  else
189  {
190  switch (*itr)
191  {
192  case 'd':
193  multiplier = DAY;
194  break;
195  case 'h':
196  multiplier = HOUR;
197  break;
198  case 'm':
199  multiplier = MINUTE;
200  break;
201  case 's':
202  multiplier = 1;
203  break;
204  default :
205  return 0; //bad format
206  }
207  buffer *= multiplier;
208  secs += buffer;
209  buffer = 0;
210  }
211  }
212 
213  return secs;
214 }
215 
216 std::string TimeToTimestampStr(time_t t)
217 {
218  tm* aTm = localtime(&t);
219  // YYYY year
220  // MM month (2 digits 01-12)
221  // DD day (2 digits 01-31)
222  // HH hour (2 digits 00-23)
223  // MM minutes (2 digits 00-59)
224  // SS seconds (2 digits 00-59)
225  char buf[20];
226  snprintf(buf, 20, "%04d-%02d-%02d_%02d-%02d-%02d", aTm->tm_year + 1900, aTm->tm_mon + 1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec);
227  return std::string(buf);
228 }
229 
230 // Check if the string is a valid ip address representation
231 bool IsIPAddress(char const* ipaddress)
232 {
233  if (!ipaddress)
234  return false;
235 
236  // Let the big boys do it.
237  // Drawback: all valid ip address formats are recognized e.g.: 12.23,121234,0xABCD)
238  return inet_addr(ipaddress) != INADDR_NONE;
239 }
240 
241 // create PID file
242 uint32 CreatePIDFile(const std::string& filename)
243 {
244  FILE* pid_file = fopen (filename.c_str(), "w" );
245  if (pid_file == NULL)
246  return 0;
247 
248  #ifdef _WIN32
249  DWORD pid = GetCurrentProcessId();
250  #else
251  pid_t pid = getpid();
252  #endif
253 
254  fprintf(pid_file, "%u", pid );
255  fclose(pid_file);
256 
257  return (uint32)pid;
258 }
259 
260 size_t utf8length(std::string& utf8str)
261 {
262  try
263  {
264  return utf8::distance(utf8str.c_str(), utf8str.c_str() + utf8str.size());
265  }
266  catch (std::exception)
267  {
268  utf8str = "";
269  return 0;
270  }
271 }
272 
273 void utf8truncate(std::string& utf8str, size_t len)
274 {
275  try
276  {
277  size_t wlen = utf8::distance(utf8str.c_str(), utf8str.c_str() + utf8str.size());
278  if (wlen <= len)
279  return;
280 
281  std::wstring wstr;
282  wstr.resize(wlen);
283  utf8::utf8to16(utf8str.c_str(), utf8str.c_str() + utf8str.size(), &wstr[0]);
284  wstr.resize(len);
285  char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str() + wstr.size(), &utf8str[0]);
286  utf8str.resize(oend - (&utf8str[0])); // remove unused tail
287  }
288  catch (std::exception)
289  {
290  utf8str = "";
291  }
292 }
293 
294 bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize)
295 {
296  try
297  {
298  size_t len = utf8::distance(utf8str, utf8str + csize);
299  if (len > wsize)
300  {
301  wsize = 0;
302  *wstr = L'\0';
303  return false;
304  }
305 
306  wsize = len;
307  utf8::utf8to16(utf8str, utf8str + csize, wstr);
308  wstr[len] = L'\0';
309  }
310  catch (std::exception)
311  {
312  wsize = 0;
313  *wstr = L'\0';
314  return false;
315  }
316 
317  return true;
318 }
319 
320 bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr)
321 {
322  try
323  {
324  size_t len = utf8::distance(utf8str.c_str(), utf8str.c_str() + utf8str.size());
325  wstr.resize(len);
326 
327  utf8::utf8to16(utf8str.c_str(), utf8str.c_str() + utf8str.size(), &wstr[0]);
328  }
329  catch (std::exception)
330  {
331  wstr = L"";
332  return false;
333  }
334 
335  return true;
336 }
337 
338 bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str)
339 {
340  try
341  {
342  std::string utf8str2;
343  utf8str2.resize(size * 4); // allocate for most long case
344 
345  char* oend = utf8::utf16to8(wstr, wstr + size, &utf8str2[0]);
346  utf8str2.resize(oend - (&utf8str2[0])); // remove unused tail
347  utf8str = utf8str2;
348  }
349  catch (std::exception)
350  {
351  utf8str = "";
352  return false;
353  }
354 
355  return true;
356 }
357 
358 bool WStrToUtf8(std::wstring wstr, std::string& utf8str)
359 {
360  try
361  {
362  std::string utf8str2;
363  utf8str2.resize(wstr.size() * 4); // allocate for most long case
364 
365  char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str() + wstr.size(), &utf8str2[0]);
366  utf8str2.resize(oend - (&utf8str2[0])); // remove unused tail
367  utf8str = utf8str2;
368  }
369  catch (std::exception)
370  {
371  utf8str = "";
372  return false;
373  }
374 
375  return true;
376 }
377 
378 typedef wchar_t const* const* wstrlist;
379 
380 std::wstring GetMainPartOfName(std::wstring wname, uint32 declension)
381 {
382  // supported only Cyrillic cases
383  if (wname.size() < 1 || !isCyrillicCharacter(wname[0]) || declension > 5)
384  return wname;
385 
386  // Important: end length must be <= MAX_INTERNAL_PLAYER_NAME-MAX_PLAYER_NAME (3 currently)
387 
388  static wchar_t const a_End[] = { wchar_t(1), wchar_t(0x0430), wchar_t(0x0000)};
389  static wchar_t const o_End[] = { wchar_t(1), wchar_t(0x043E), wchar_t(0x0000)};
390  static wchar_t const ya_End[] = { wchar_t(1), wchar_t(0x044F), wchar_t(0x0000)};
391  static wchar_t const ie_End[] = { wchar_t(1), wchar_t(0x0435), wchar_t(0x0000)};
392  static wchar_t const i_End[] = { wchar_t(1), wchar_t(0x0438), wchar_t(0x0000)};
393  static wchar_t const yeru_End[] = { wchar_t(1), wchar_t(0x044B), wchar_t(0x0000)};
394  static wchar_t const u_End[] = { wchar_t(1), wchar_t(0x0443), wchar_t(0x0000)};
395  static wchar_t const yu_End[] = { wchar_t(1), wchar_t(0x044E), wchar_t(0x0000)};
396  static wchar_t const oj_End[] = { wchar_t(2), wchar_t(0x043E), wchar_t(0x0439), wchar_t(0x0000)};
397  static wchar_t const ie_j_End[] = { wchar_t(2), wchar_t(0x0435), wchar_t(0x0439), wchar_t(0x0000)};
398  static wchar_t const io_j_End[] = { wchar_t(2), wchar_t(0x0451), wchar_t(0x0439), wchar_t(0x0000)};
399  static wchar_t const o_m_End[] = { wchar_t(2), wchar_t(0x043E), wchar_t(0x043C), wchar_t(0x0000)};
400  static wchar_t const io_m_End[] = { wchar_t(2), wchar_t(0x0451), wchar_t(0x043C), wchar_t(0x0000)};
401  static wchar_t const ie_m_End[] = { wchar_t(2), wchar_t(0x0435), wchar_t(0x043C), wchar_t(0x0000)};
402  static wchar_t const soft_End[] = { wchar_t(1), wchar_t(0x044C), wchar_t(0x0000)};
403  static wchar_t const j_End[] = { wchar_t(1), wchar_t(0x0439), wchar_t(0x0000)};
404 
405  static wchar_t const* const dropEnds[6][8] =
406  {
407  { &a_End[1], &o_End[1], &ya_End[1], &ie_End[1], &soft_End[1], &j_End[1], NULL, NULL },
408  { &a_End[1], &ya_End[1], &yeru_End[1], &i_End[1], NULL, NULL, NULL, NULL },
409  { &ie_End[1], &u_End[1], &yu_End[1], &i_End[1], NULL, NULL, NULL, NULL },
410  { &u_End[1], &yu_End[1], &o_End[1], &ie_End[1], &soft_End[1], &ya_End[1], &a_End[1], NULL },
411  { &oj_End[1], &io_j_End[1], &ie_j_End[1], &o_m_End[1], &io_m_End[1], &ie_m_End[1], &yu_End[1], NULL },
412  { &ie_End[1], &i_End[1], NULL, NULL, NULL, NULL, NULL, NULL }
413  };
414 
415  for (wchar_t const * const* itr = &dropEnds[declension][0]; *itr; ++itr)
416  {
417  size_t len = size_t((*itr)[-1]); // get length from string size field
418 
419  if (wname.substr(wname.size() - len, len) == *itr)
420  return wname.substr(0, wname.size() - len);
421  }
422 
423  return wname;
424 }
425 
426 bool utf8ToConsole(const std::string& utf8str, std::string& conStr)
427 {
428  #if PLATFORM == PLATFORM_WINDOWS
429  std::wstring wstr;
430  if (!Utf8toWStr(utf8str, wstr))
431  return false;
432 
433  conStr.resize(wstr.size());
434  CharToOemBuffW(&wstr[0], &conStr[0], wstr.size());
435  #else
436  // not implemented yet
437  conStr = utf8str;
438  #endif
439 
440  return true;
441 }
442 
443 bool consoleToUtf8(const std::string& conStr, std::string& utf8str)
444 {
445  #if PLATFORM == PLATFORM_WINDOWS
446  std::wstring wstr;
447  wstr.resize(conStr.size());
448  OemToCharBuffW(&conStr[0], &wstr[0], conStr.size());
449 
450  return WStrToUtf8(wstr, utf8str);
451  #else
452  // not implemented yet
453  utf8str = conStr;
454  return true;
455  #endif
456 }
457 
458 bool Utf8FitTo(const std::string& str, std::wstring search)
459 {
460  std::wstring temp;
461 
462  if (!Utf8toWStr(str, temp))
463  return false;
464 
465  // converting to lower case
466  wstrToLower( temp );
467 
468  if (temp.find(search) == std::wstring::npos)
469  return false;
470 
471  return true;
472 }
473 
474 void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result)
475 {
476  std::ostringstream ss;
477  for (uint32 i = 0; i < arrayLen; ++i)
478  {
479  for (uint8 j = 0; j < 2; ++j)
480  {
481  unsigned char nibble = 0x0F & (bytes[i] >> ((1 - j) * 4));
482  char encodedNibble;
483  if (nibble < 0x0A)
484  encodedNibble = '0' + nibble;
485  else
486  encodedNibble = 'A' + nibble - 0x0A;
487  ss << encodedNibble;
488  }
489  }
490  result = ss.str();
491 }
492 
493 std::string ByteArrayToHexStr(uint8* bytes, uint32 length)
494 {
495  std::ostringstream ss;
496  for (uint32 i = 0; i < length; ++i)
497  {
498  char buffer[4];
499  sprintf(buffer, "%02X", bytes[i]);
500  ss << buffer;
501  }
502 
503  return ss.str();
504 }
ACE_TSS< MTRand > MTRandTSS
Definition: Util.cpp:63
bool Utf8FitTo(const std::string &str, std::wstring search)
Definition: Util.cpp:458
#define snprintf
Definition: Common.h:129
std::vector< std::string > Tokens
Definition: Util.h:26
bool isCyrillicCharacter(wchar_t wchar)
Definition: Util.h:172
void utf8truncate(std::string &utf8str, size_t len)
Definition: Util.cpp:273
std::wstring GetMainPartOfName(std::wstring wname, uint32 declension)
Definition: Util.cpp:380
int32 irand(int32 min, int32 max)
Definition: Util.cpp:66
bool consoleToUtf8(const std::string &conStr, std::string &utf8str)
Definition: Util.cpp:443
Tokens StrSplit(const std::string &src, const std::string &sep)
Definition: Util.cpp:97
ACE_INT32 int32
Definition: Define.h:67
size_t utf8length(std::string &utf8str)
Definition: Util.cpp:260
wchar_t const *const * wstrlist
Definition: Util.cpp:378
bool Utf8toWStr(char const *utf8str, size_t csize, wchar_t *wstr, size_t &wsize)
Definition: Util.cpp:294
void wstrToLower(std::wstring &str)
Definition: Util.h:314
bool WStrToUtf8(wchar_t *wstr, size_t size, std::string &utf8str)
Definition: Util.cpp:338
Definition: Common.h:181
Definition: Common.h:179
ACE_UINT8 uint8
Definition: Define.h:73
double rand_chance(void)
Definition: Util.cpp:91
float frand(float min, float max)
Definition: Util.cpp:76
uint32 TimeStringToSecs(const std::string &timestring)
Definition: Util.cpp:171
std::string ByteArrayToHexStr(uint8 *bytes, uint32 length)
Definition: Util.cpp:493
bool IsIPAddress(char const *ipaddress)
Definition: Util.cpp:231
void hexEncodeByteArray(uint8 *bytes, uint32 arrayLen, std::string &result)
Definition: Util.cpp:474
std::string TimeToTimestampStr(time_t t)
Definition: Util.cpp:216
std::string secsToTimeString(uint32 timeInSecs, bool shortText, bool hoursOnly)
Definition: Util.cpp:148
bool utf8ToConsole(const std::string &utf8str, std::string &conStr)
Definition: Util.cpp:426
Definition: Common.h:180
double rand_norm(void)
Definition: Util.cpp:86
uint32 CreatePIDFile(const std::string &filename)
Definition: Util.cpp:242
ACE_UINT32 uint32
Definition: Define.h:71
int32 rand32()
Definition: Util.cpp:81
uint32 urand(uint32 min, uint32 max)
Definition: Util.cpp:71
void stripLineInvisibleChars(std::string &str)
Definition: Util.cpp:115