[9133] Fixes in talent 11129 work.
[getmangos.git] / src / shared / Util.cpp
blob7584d8c8ac485d585eae2e77b1c847779d6a4ea6
1 /*
2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Util.h"
21 #include "sockets/socket_include.h"
22 #include "utf8cpp/utf8.h"
23 #include "mersennetwister/MersenneTwister.h"
24 #include <ace/TSS_T.h>
26 typedef ACE_TSS<MTRand> MTRandTSS;
27 static MTRandTSS mtRand;
29 int32 irand (int32 min, int32 max)
31 return int32 (mtRand->randInt (max - min)) + min;
34 uint32 urand (uint32 min, uint32 max)
36 return mtRand->randInt (max - min) + min;
39 int32 rand32 ()
41 return mtRand->randInt ();
44 double rand_norm(void)
46 return mtRand->randExc ();
49 double rand_chance (void)
51 return mtRand->randExc (100.0);
54 Tokens StrSplit(const std::string &src, const std::string &sep)
56 Tokens r;
57 std::string s;
58 for (std::string::const_iterator i = src.begin(); i != src.end(); i++)
60 if (sep.find(*i) != std::string::npos)
62 if (s.length()) r.push_back(s);
63 s = "";
65 else
67 s += *i;
70 if (s.length()) r.push_back(s);
71 return r;
74 void stripLineInvisibleChars(std::string &str)
76 static std::string invChars = " \t\7\n";
78 size_t wpos = 0;
80 bool space = false;
81 for(size_t pos = 0; pos < str.size(); ++pos)
83 if(invChars.find(str[pos])!=std::string::npos)
85 if(!space)
87 str[wpos++] = ' ';
88 space = true;
91 else
93 if(wpos!=pos)
94 str[wpos++] = str[pos];
95 else
96 ++wpos;
97 space = false;
101 if(wpos < str.size())
102 str.erase(wpos,str.size());
105 std::string secsToTimeString(uint32 timeInSecs, bool shortText, bool hoursOnly)
107 uint32 secs = timeInSecs % MINUTE;
108 uint32 minutes = timeInSecs % HOUR / MINUTE;
109 uint32 hours = timeInSecs % DAY / HOUR;
110 uint32 days = timeInSecs / DAY;
112 std::ostringstream ss;
113 if(days)
114 ss << days << (shortText ? "d" : " Day(s) ");
115 if(hours || hoursOnly)
116 ss << hours << (shortText ? "h" : " Hour(s) ");
117 if(!hoursOnly)
119 if(minutes)
120 ss << minutes << (shortText ? "m" : " Minute(s) ");
121 if(secs || (!days && !hours && !minutes) )
122 ss << secs << (shortText ? "s" : " Second(s).");
125 return ss.str();
128 uint32 TimeStringToSecs(const std::string& timestring)
130 uint32 secs = 0;
131 uint32 buffer = 0;
132 uint32 multiplier = 0;
134 for(std::string::const_iterator itr = timestring.begin(); itr != timestring.end(); itr++ )
136 if(isdigit(*itr))
138 buffer*=10;
139 buffer+= (*itr)-'0';
141 else
143 switch(*itr)
145 case 'd': multiplier = DAY; break;
146 case 'h': multiplier = HOUR; break;
147 case 'm': multiplier = MINUTE; break;
148 case 's': multiplier = 1; break;
149 default : return 0; //bad format
151 buffer*=multiplier;
152 secs+=buffer;
153 buffer=0;
157 return secs;
160 std::string TimeToTimestampStr(time_t t)
162 tm* aTm = localtime(&t);
163 // YYYY year
164 // MM month (2 digits 01-12)
165 // DD day (2 digits 01-31)
166 // HH hour (2 digits 00-23)
167 // MM minutes (2 digits 00-59)
168 // SS seconds (2 digits 00-59)
169 char buf[20];
170 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);
171 return std::string(buf);
174 /// Check if the string is a valid ip address representation
175 bool IsIPAddress(char const* ipaddress)
177 if(!ipaddress)
178 return false;
180 // Let the big boys do it.
181 // Drawback: all valid ip address formats are recognized e.g.: 12.23,121234,0xABCD)
182 return inet_addr(ipaddress) != INADDR_NONE;
185 /// create PID file
186 uint32 CreatePIDFile(const std::string& filename)
188 FILE * pid_file = fopen (filename.c_str(), "w" );
189 if (pid_file == NULL)
190 return 0;
192 #ifdef WIN32
193 DWORD pid = GetCurrentProcessId();
194 #else
195 pid_t pid = getpid();
196 #endif
198 fprintf(pid_file, "%d", pid );
199 fclose(pid_file);
201 return (uint32)pid;
204 size_t utf8length(std::string& utf8str)
208 return utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size());
210 catch(std::exception)
212 utf8str = "";
213 return 0;
217 void utf8truncate(std::string& utf8str,size_t len)
221 size_t wlen = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size());
222 if(wlen <= len)
223 return;
225 std::wstring wstr;
226 wstr.resize(wlen);
227 utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]);
228 wstr.resize(len);
229 char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str[0]);
230 utf8str.resize(oend-(&utf8str[0])); // remove unused tail
232 catch(std::exception)
234 utf8str = "";
238 bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize)
242 size_t len = utf8::distance(utf8str,utf8str+csize);
243 if(len > wsize)
245 if(wsize > 0)
246 wstr[0] = L'\0';
247 wsize = 0;
248 return false;
251 wsize = len;
252 utf8::utf8to16(utf8str,utf8str+csize,wstr);
253 wstr[len] = L'\0';
255 catch(std::exception)
257 if(wsize > 0)
258 wstr[0] = L'\0';
259 wsize = 0;
260 return false;
263 return true;
266 bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr)
270 size_t len = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size());
271 wstr.resize(len);
273 utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]);
275 catch(std::exception)
277 wstr = L"";
278 return false;
281 return true;
284 bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str)
288 std::string utf8str2;
289 utf8str2.resize(size*4); // allocate for most long case
291 char* oend = utf8::utf16to8(wstr,wstr+size,&utf8str2[0]);
292 utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail
293 utf8str = utf8str2;
295 catch(std::exception)
297 utf8str = "";
298 return false;
301 return true;
304 bool WStrToUtf8(std::wstring wstr, std::string& utf8str)
308 std::string utf8str2;
309 utf8str2.resize(wstr.size()*4); // allocate for most long case
311 char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str2[0]);
312 utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail
313 utf8str = utf8str2;
315 catch(std::exception)
317 utf8str = "";
318 return false;
321 return true;
324 typedef wchar_t const* const* wstrlist;
326 std::wstring GetMainPartOfName(std::wstring wname, uint32 declension)
328 // supported only Cyrillic cases
329 if(wname.size() < 1 || !isCyrillicCharacter(wname[0]) || declension > 5)
330 return wname;
332 // Important: end length must be <= MAX_INTERNAL_PLAYER_NAME-MAX_PLAYER_NAME (3 currently)
334 static wchar_t const a_End[] = { wchar_t(1), wchar_t(0x0430),wchar_t(0x0000)};
335 static wchar_t const o_End[] = { wchar_t(1), wchar_t(0x043E),wchar_t(0x0000)};
336 static wchar_t const ya_End[] = { wchar_t(1), wchar_t(0x044F),wchar_t(0x0000)};
337 static wchar_t const ie_End[] = { wchar_t(1), wchar_t(0x0435),wchar_t(0x0000)};
338 static wchar_t const i_End[] = { wchar_t(1), wchar_t(0x0438),wchar_t(0x0000)};
339 static wchar_t const yeru_End[] = { wchar_t(1), wchar_t(0x044B),wchar_t(0x0000)};
340 static wchar_t const u_End[] = { wchar_t(1), wchar_t(0x0443),wchar_t(0x0000)};
341 static wchar_t const yu_End[] = { wchar_t(1), wchar_t(0x044E),wchar_t(0x0000)};
342 static wchar_t const oj_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x0439),wchar_t(0x0000)};
343 static wchar_t const ie_j_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x0439),wchar_t(0x0000)};
344 static wchar_t const io_j_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x0439),wchar_t(0x0000)};
345 static wchar_t const o_m_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x043C),wchar_t(0x0000)};
346 static wchar_t const io_m_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x043C),wchar_t(0x0000)};
347 static wchar_t const ie_m_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x043C),wchar_t(0x0000)};
348 static wchar_t const soft_End[] = { wchar_t(1), wchar_t(0x044C),wchar_t(0x0000)};
349 static wchar_t const j_End[] = { wchar_t(1), wchar_t(0x0439),wchar_t(0x0000)};
351 static wchar_t const* const dropEnds[6][8] = {
352 { &a_End[1], &o_End[1], &ya_End[1], &ie_End[1], &soft_End[1], &j_End[1], NULL, NULL },
353 { &a_End[1], &ya_End[1], &yeru_End[1], &i_End[1], NULL, NULL, NULL, NULL },
354 { &ie_End[1], &u_End[1], &yu_End[1], &i_End[1], NULL, NULL, NULL, NULL },
355 { &u_End[1], &yu_End[1], &o_End[1], &ie_End[1], &soft_End[1], &ya_End[1], &a_End[1], NULL },
356 { &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 },
357 { &ie_End[1], &i_End[1], NULL, NULL, NULL, NULL, NULL, NULL }
360 for(wchar_t const * const* itr = &dropEnds[declension][0]; *itr; ++itr)
362 size_t len = size_t((*itr)[-1]); // get length from string size field
364 if(wname.substr(wname.size()-len,len)==*itr)
365 return wname.substr(0,wname.size()-len);
368 return wname;
371 bool utf8ToConsole(const std::string& utf8str, std::string& conStr)
373 #if PLATFORM == PLATFORM_WINDOWS
374 std::wstring wstr;
375 if(!Utf8toWStr(utf8str,wstr))
376 return false;
378 conStr.resize(wstr.size());
379 CharToOemBuffW(&wstr[0],&conStr[0],wstr.size());
380 #else
381 // not implemented yet
382 conStr = utf8str;
383 #endif
385 return true;
388 bool consoleToUtf8(const std::string& conStr,std::string& utf8str)
390 #if PLATFORM == PLATFORM_WINDOWS
391 std::wstring wstr;
392 wstr.resize(conStr.size());
393 OemToCharBuffW(&conStr[0],&wstr[0],conStr.size());
395 return WStrToUtf8(wstr,utf8str);
396 #else
397 // not implemented yet
398 utf8str = conStr;
399 return true;
400 #endif
403 bool Utf8FitTo(const std::string& str, std::wstring search)
405 std::wstring temp;
407 if(!Utf8toWStr(str,temp))
408 return false;
410 // converting to lower case
411 wstrToLower( temp );
413 if(temp.find(search) == std::wstring::npos)
414 return false;
416 return true;
419 void utf8printf(FILE *out, const char *str, ...)
421 va_list ap;
422 va_start(ap, str);
423 vutf8printf(stdout, str, &ap);
424 va_end(ap);
427 void vutf8printf(FILE *out, const char *str, va_list* ap)
429 #if PLATFORM == PLATFORM_WINDOWS
430 char temp_buf[32*1024];
431 wchar_t wtemp_buf[32*1024];
433 size_t temp_len = vsnprintf(temp_buf, 32*1024, str, *ap);
435 size_t wtemp_len = 32*1024-1;
436 Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len);
438 CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], wtemp_len+1);
439 fprintf(out, temp_buf);
440 #else
441 vfprintf(out, str, *ap);
442 #endif
445 void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result)
447 std::ostringstream ss;
448 for(uint32 i=0; i<arrayLen; ++i)
450 for(uint8 j=0; j<2; ++j)
452 unsigned char nibble = 0x0F & (bytes[i]>>((1-j)*4));
453 char encodedNibble;
454 if(nibble < 0x0A)
455 encodedNibble = '0'+nibble;
456 else
457 encodedNibble = 'A'+nibble-0x0A;
458 ss << encodedNibble;
461 result = ss.str();