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