[7297] Fixed profession spells sorting in trainer spell list at client.
[getmangos.git] / src / shared / Util.cpp
blob519c612af0842df75f48107b3700869aa6afdd0f
1 /*
2 * Copyright (C) 2005-2009 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 "zthread/ThreadLocal.h"
26 typedef ZThread::ThreadLocal<MTRand> MTRandTSS;
28 /* NOTE: Not sure if static initialization is ok for TSS objects ,
29 * as I see zthread uses custom implementation of the TSS
30 * ,and in the consturctor there is no code ,so I suppose its ok
31 * If its not ok ,change it to use singleton.
33 static MTRandTSS mtRand;
35 int32 irand (int32 min, int32 max)
37 return int32 (mtRand.get ().randInt (max - min)) + min;
40 uint32 urand (uint32 min, uint32 max)
42 return mtRand.get ().randInt (max - min) + min;
45 int32 rand32 ()
47 return mtRand.get ().randInt ();
50 double rand_norm(void)
52 return mtRand.get ().randExc ();
55 double rand_chance (void)
57 return mtRand.get ().randExc (100.0);
60 Tokens StrSplit(const std::string &src, const std::string &sep)
62 Tokens r;
63 std::string s;
64 for (std::string::const_iterator i = src.begin(); i != src.end(); i++)
66 if (sep.find(*i) != std::string::npos)
68 if (s.length()) r.push_back(s);
69 s = "";
71 else
73 s += *i;
76 if (s.length()) r.push_back(s);
77 return r;
80 void stripLineInvisibleChars(std::string &str)
82 static std::string invChars = " \t\7";
84 size_t wpos = 0;
86 bool space = false;
87 for(size_t pos = 0; pos < str.size(); ++pos)
89 if(invChars.find(str[pos])!=std::string::npos)
91 if(!space)
93 str[wpos++] = ' ';
94 space = true;
97 else
99 if(wpos!=pos)
100 str[wpos++] = str[pos];
101 else
102 ++wpos;
103 space = false;
107 if(wpos < str.size())
108 str.erase(wpos,str.size());
111 std::string secsToTimeString(uint32 timeInSecs, bool shortText, bool hoursOnly)
113 uint32 secs = timeInSecs % MINUTE;
114 uint32 minutes = timeInSecs % HOUR / MINUTE;
115 uint32 hours = timeInSecs % DAY / HOUR;
116 uint32 days = timeInSecs / DAY;
118 std::ostringstream ss;
119 if(days)
120 ss << days << (shortText ? "d" : " Day(s) ");
121 if(hours || hoursOnly)
122 ss << hours << (shortText ? "h" : " Hour(s) ");
123 if(!hoursOnly)
125 if(minutes)
126 ss << minutes << (shortText ? "m" : " Minute(s) ");
127 if(secs || (!days && !hours && !minutes) )
128 ss << secs << (shortText ? "s" : " Second(s).");
131 return ss.str();
134 uint32 TimeStringToSecs(const std::string& timestring)
136 uint32 secs = 0;
137 uint32 buffer = 0;
138 uint32 multiplier = 0;
140 for(std::string::const_iterator itr = timestring.begin(); itr != timestring.end(); itr++ )
142 if(isdigit(*itr))
144 std::string str; //very complicated typecast char->const char*; is there no better way?
145 str += *itr;
146 const char* tmp = str.c_str();
148 buffer*=10;
149 buffer+=atoi(tmp);
151 else
153 switch(*itr)
155 case 'd': multiplier = DAY; break;
156 case 'h': multiplier = HOUR; break;
157 case 'm': multiplier = MINUTE; break;
158 case 's': multiplier = 1; break;
159 default : return 0; //bad format
161 buffer*=multiplier;
162 secs+=buffer;
163 buffer=0;
167 return secs;
170 std::string TimeToTimestampStr(time_t t)
172 tm* aTm = localtime(&t);
173 // YYYY year
174 // MM month (2 digits 01-12)
175 // DD day (2 digits 01-31)
176 // HH hour (2 digits 00-23)
177 // MM minutes (2 digits 00-59)
178 // SS seconds (2 digits 00-59)
179 char buf[20];
180 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);
181 return std::string(buf);
184 /// Check if the string is a valid ip address representation
185 bool IsIPAddress(char const* ipaddress)
187 if(!ipaddress)
188 return false;
190 // Let the big boys do it.
191 // Drawback: all valid ip address formats are recognized e.g.: 12.23,121234,0xABCD)
192 return inet_addr(ipaddress) != INADDR_NONE;
195 /// create PID file
196 uint32 CreatePIDFile(const std::string& filename)
198 FILE * pid_file = fopen (filename.c_str(), "w" );
199 if (pid_file == NULL)
200 return 0;
202 #ifdef WIN32
203 DWORD pid = GetCurrentProcessId();
204 #else
205 pid_t pid = getpid();
206 #endif
208 fprintf(pid_file, "%d", pid );
209 fclose(pid_file);
211 return (uint32)pid;
214 size_t utf8length(std::string& utf8str)
218 return utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size());
220 catch(std::exception)
222 utf8str = "";
223 return 0;
227 void utf8truncate(std::string& utf8str,size_t len)
231 size_t wlen = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size());
232 if(wlen <= len)
233 return;
235 std::wstring wstr;
236 wstr.resize(wlen);
237 utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]);
238 wstr.resize(len);
239 char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str[0]);
240 utf8str.resize(oend-(&utf8str[0])); // remove unused tail
242 catch(std::exception)
244 utf8str = "";
248 bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize)
252 size_t len = utf8::distance(utf8str,utf8str+csize);
253 if(len > wsize)
255 if(wsize > 0)
256 wstr[0] = L'\0';
257 wsize = 0;
258 return false;
261 wsize = len;
262 utf8::utf8to16(utf8str,utf8str+csize,wstr);
263 wstr[len] = L'\0';
265 catch(std::exception)
267 if(wsize > 0)
268 wstr[0] = L'\0';
269 wsize = 0;
270 return false;
273 return true;
276 bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr)
280 size_t len = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size());
281 wstr.resize(len);
283 utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]);
285 catch(std::exception)
287 wstr = L"";
288 return false;
291 return true;
294 bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str)
298 std::string utf8str2;
299 utf8str2.resize(size*4); // allocate for most long case
301 char* oend = utf8::utf16to8(wstr,wstr+size,&utf8str2[0]);
302 utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail
303 utf8str = utf8str2;
305 catch(std::exception)
307 utf8str = "";
308 return false;
311 return true;
314 bool WStrToUtf8(std::wstring wstr, std::string& utf8str)
318 std::string utf8str2;
319 utf8str2.resize(wstr.size()*4); // allocate for most long case
321 char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str2[0]);
322 utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail
323 utf8str = utf8str2;
325 catch(std::exception)
327 utf8str = "";
328 return false;
331 return true;
334 typedef wchar_t const* const* wstrlist;
336 std::wstring GetMainPartOfName(std::wstring wname, uint32 declension)
338 // supported only Cyrillic cases
339 if(wname.size() < 1 || !isCyrillicCharacter(wname[0]) || declension > 5)
340 return wname;
342 // Important: end length must be <= MAX_INTERNAL_PLAYER_NAME-MAX_PLAYER_NAME (3 currently)
344 static wchar_t const a_End[] = { wchar_t(1), wchar_t(0x0430),wchar_t(0x0000)};
345 static wchar_t const o_End[] = { wchar_t(1), wchar_t(0x043E),wchar_t(0x0000)};
346 static wchar_t const ya_End[] = { wchar_t(1), wchar_t(0x044F),wchar_t(0x0000)};
347 static wchar_t const ie_End[] = { wchar_t(1), wchar_t(0x0435),wchar_t(0x0000)};
348 static wchar_t const i_End[] = { wchar_t(1), wchar_t(0x0438),wchar_t(0x0000)};
349 static wchar_t const yeru_End[] = { wchar_t(1), wchar_t(0x044B),wchar_t(0x0000)};
350 static wchar_t const u_End[] = { wchar_t(1), wchar_t(0x0443),wchar_t(0x0000)};
351 static wchar_t const yu_End[] = { wchar_t(1), wchar_t(0x044E),wchar_t(0x0000)};
352 static wchar_t const oj_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x0439),wchar_t(0x0000)};
353 static wchar_t const ie_j_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x0439),wchar_t(0x0000)};
354 static wchar_t const io_j_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x0439),wchar_t(0x0000)};
355 static wchar_t const o_m_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x043C),wchar_t(0x0000)};
356 static wchar_t const io_m_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x043C),wchar_t(0x0000)};
357 static wchar_t const ie_m_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x043C),wchar_t(0x0000)};
358 static wchar_t const soft_End[] = { wchar_t(1), wchar_t(0x044C),wchar_t(0x0000)};
359 static wchar_t const j_End[] = { wchar_t(1), wchar_t(0x0439),wchar_t(0x0000)};
361 static wchar_t const* const dropEnds[6][8] = {
362 { &a_End[1], &o_End[1], &ya_End[1], &ie_End[1], &soft_End[1], &j_End[1], NULL, NULL },
363 { &a_End[1], &ya_End[1], &yeru_End[1], &i_End[1], NULL, NULL, NULL, NULL },
364 { &ie_End[1], &u_End[1], &yu_End[1], &i_End[1], NULL, NULL, NULL, NULL },
365 { &u_End[1], &yu_End[1], &o_End[1], &ie_End[1], &soft_End[1], &ya_End[1], &a_End[1], NULL },
366 { &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 },
367 { &ie_End[1], &i_End[1], NULL, NULL, NULL, NULL, NULL, NULL }
370 for(wchar_t const * const* itr = &dropEnds[declension][0]; *itr; ++itr)
372 size_t len = size_t((*itr)[-1]); // get length from string size field
374 if(wname.substr(wname.size()-len,len)==*itr)
375 return wname.substr(0,wname.size()-len);
378 return wname;
381 bool utf8ToConsole(const std::string& utf8str, std::string& conStr)
383 #if PLATFORM == PLATFORM_WINDOWS
384 std::wstring wstr;
385 if(!Utf8toWStr(utf8str,wstr))
386 return false;
388 conStr.resize(wstr.size());
389 CharToOemBuffW(&wstr[0],&conStr[0],wstr.size());
390 #else
391 // not implemented yet
392 conStr = utf8str;
393 #endif
395 return true;
398 bool consoleToUtf8(const std::string& conStr,std::string& utf8str)
400 #if PLATFORM == PLATFORM_WINDOWS
401 std::wstring wstr;
402 wstr.resize(conStr.size());
403 OemToCharBuffW(&conStr[0],&wstr[0],conStr.size());
405 return WStrToUtf8(wstr,utf8str);
406 #else
407 // not implemented yet
408 utf8str = conStr;
409 return true;
410 #endif
413 bool Utf8FitTo(const std::string& str, std::wstring search)
415 std::wstring temp;
417 if(!Utf8toWStr(str,temp))
418 return false;
420 // converting to lower case
421 wstrToLower( temp );
423 if(temp.find(search) == std::wstring::npos)
424 return false;
426 return true;