diff options
Diffstat (limited to 'src/shared/Util.cpp')
-rw-r--r-- | src/shared/Util.cpp | 425 |
1 files changed, 425 insertions, 0 deletions
diff --git a/src/shared/Util.cpp b/src/shared/Util.cpp new file mode 100644 index 00000000000..c5e8284534d --- /dev/null +++ b/src/shared/Util.cpp @@ -0,0 +1,425 @@ +/* + * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Util.h" + +#include "sockets/socket_include.h" +#include "utf8cpp/utf8.h" +#include "mersennetwister/MersenneTwister.h" +#include "zthread/ThreadLocal.h" + +typedef ZThread::ThreadLocal<MTRand> MTRandTSS; + +/* NOTE: Not sure if static initialization is ok for TSS objects , + * as I see zthread uses custom implementation of the TSS + * ,and in the consturctor there is no code ,so I suppose its ok + * If its not ok ,change it to use singleton. + */ +static MTRandTSS mtRand; + +int32 irand (int32 min, int32 max) +{ + return int32 (mtRand.get ().randInt (max - min)) + min; +} + +uint32 urand (uint32 min, uint32 max) +{ + return mtRand.get ().randInt (max - min) + min; +} + +int32 rand32 () +{ + return mtRand.get ().randInt (); +} + +double rand_norm(void) +{ + return mtRand.get ().randExc (); +} + +double rand_chance (void) +{ + return mtRand.get ().randExc (100.0); +} + +Tokens StrSplit(const std::string &src, const std::string &sep) +{ + Tokens r; + std::string s; + for (std::string::const_iterator i = src.begin(); i != src.end(); i++) + { + if (sep.find(*i) != std::string::npos) + { + if (s.length()) r.push_back(s); + s = ""; + } + else + { + s += *i; + } + } + if (s.length()) r.push_back(s); + return r; +} + +void stripLineInvisibleChars(std::string &str) +{ + static std::string invChars = " \t\7"; + + size_t wpos = 0; + + bool space = false; + for(size_t pos = 0; pos < str.size(); ++pos) + { + if(invChars.find(str[pos])!=std::string::npos) + { + if(!space) + { + str[wpos++] = ' '; + space = true; + } + } + else + { + if(wpos!=pos) + str[wpos++] = str[pos]; + else + ++wpos; + space = false; + } + } + + if(wpos < str.size()) + str.erase(wpos,str.size()); +} + +std::string secsToTimeString(uint32 timeInSecs, bool shortText, bool hoursOnly) +{ + uint32 secs = timeInSecs % MINUTE; + uint32 minutes = timeInSecs % HOUR / MINUTE; + uint32 hours = timeInSecs % DAY / HOUR; + uint32 days = timeInSecs / DAY; + + std::ostringstream ss; + if(days) + ss << days << (shortText ? "d" : " Day(s) "); + if(hours || hoursOnly) + ss << hours << (shortText ? "h" : " Hour(s) "); + if(!hoursOnly) + { + if(minutes) + ss << minutes << (shortText ? "m" : " Minute(s) "); + if(secs || (!days && !hours && !minutes) ) + ss << secs << (shortText ? "s" : " Second(s)."); + } + + return ss.str(); +} + +uint32 TimeStringToSecs(std::string timestring) +{ + uint32 secs = 0; + uint32 buffer = 0; + uint32 multiplier = 0; + + for(std::string::iterator itr = timestring.begin(); itr != timestring.end(); itr++ ) + { + if(isdigit(*itr)) + { + std::string str; //very complicated typecast char->const char*; is there no better way? + str += *itr; + const char* tmp = str.c_str(); + + buffer*=10; + buffer+=atoi(tmp); + } + else + { + switch(*itr) + { + case 'd': multiplier = DAY; break; + case 'h': multiplier = HOUR; break; + case 'm': multiplier = MINUTE; break; + case 's': multiplier = 1; break; + default : return 0; //bad format + } + buffer*=multiplier; + secs+=buffer; + buffer=0; + } + } + + return secs; +} + +std::string TimeToTimestampStr(time_t t) +{ + tm* aTm = localtime(&t); + // YYYY year + // MM month (2 digits 01-12) + // DD day (2 digits 01-31) + // HH hour (2 digits 00-23) + // MM minutes (2 digits 00-59) + // SS seconds (2 digits 00-59) + char buf[20]; + 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); + return std::string(buf); +} + +/// Check if the string is a valid ip address representation +bool IsIPAddress(char const* ipaddress) +{ + if(!ipaddress) + return false; + + // Let the big boys do it. + // Drawback: all valid ip address formats are recognized e.g.: 12.23,121234,0xABCD) + return inet_addr(ipaddress) != INADDR_NONE; +} + +/// create PID file +uint32 CreatePIDFile(std::string filename) +{ + FILE * pid_file = fopen (filename.c_str(), "w" ); + if (pid_file == NULL) + return 0; + +#ifdef WIN32 + DWORD pid = GetCurrentProcessId(); +#else + pid_t pid = getpid(); +#endif + + fprintf(pid_file, "%d", pid ); + fclose(pid_file); + + return (uint32)pid; +} + +size_t utf8length(std::string& utf8str) +{ + try + { + return utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size()); + } + catch(std::exception) + { + utf8str = ""; + return 0; + } +} + +void utf8truncate(std::string& utf8str,size_t len) +{ + try + { + size_t wlen = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size()); + if(wlen <= len) + return; + + std::wstring wstr; + wstr.resize(wlen); + utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]); + wstr.resize(len); + char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str[0]); + utf8str.resize(oend-(&utf8str[0])); // remove unused tail + } + catch(std::exception) + { + utf8str = ""; + } +} + +bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize) +{ + try + { + size_t len = utf8::distance(utf8str,utf8str+csize); + if(len > wsize) + { + wsize = 0; + wstr = L""; + return false; + } + + wsize = len; + utf8::utf8to16(utf8str,utf8str+csize,wstr); + wstr[len] = L'\0'; + } + catch(std::exception) + { + wsize = 0; + wstr = L""; + return false; + } + + return true; +} + +bool Utf8toWStr(std::string utf8str, std::wstring& wstr) +{ + try + { + size_t len = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size()); + wstr.resize(len); + + utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]); + } + catch(std::exception) + { + wstr = L""; + return false; + } + + return true; +} + +bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str) +{ + try + { + std::string utf8str2; + utf8str2.resize(size*4); // allocate for most long case + + char* oend = utf8::utf16to8(wstr,wstr+size,&utf8str2[0]); + utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail + utf8str = utf8str2; + } + catch(std::exception) + { + utf8str = ""; + return false; + } + + return true; +} + +bool WStrToUtf8(std::wstring wstr, std::string& utf8str) +{ + try + { + std::string utf8str2; + utf8str2.resize(wstr.size()*4); // allocate for most long case + + char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str2[0]); + utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail + utf8str = utf8str2; + } + catch(std::exception) + { + utf8str = ""; + return false; + } + + return true; +} + +typedef wchar_t const* const* wstrlist; + +std::wstring GetMainPartOfName(std::wstring wname, uint32 declension) +{ + // supported only Cyrillic cases + if(wname.size() < 1 || !isCyrillicCharacter(wname[0]) || declension > 5) + return wname; + + // Important: end length must be <= MAX_INTERNAL_PLAYER_NAME-MAX_PLAYER_NAME (3 currently) + + static wchar_t const a_End[] = { wchar_t(1), wchar_t(0x0430),wchar_t(0x0000)}; + static wchar_t const o_End[] = { wchar_t(1), wchar_t(0x043E),wchar_t(0x0000)}; + static wchar_t const ya_End[] = { wchar_t(1), wchar_t(0x044F),wchar_t(0x0000)}; + static wchar_t const ie_End[] = { wchar_t(1), wchar_t(0x0435),wchar_t(0x0000)}; + static wchar_t const i_End[] = { wchar_t(1), wchar_t(0x0438),wchar_t(0x0000)}; + static wchar_t const yeru_End[] = { wchar_t(1), wchar_t(0x044B),wchar_t(0x0000)}; + static wchar_t const u_End[] = { wchar_t(1), wchar_t(0x0443),wchar_t(0x0000)}; + static wchar_t const yu_End[] = { wchar_t(1), wchar_t(0x044E),wchar_t(0x0000)}; + static wchar_t const oj_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x0439),wchar_t(0x0000)}; + static wchar_t const ie_j_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x0439),wchar_t(0x0000)}; + static wchar_t const io_j_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x0439),wchar_t(0x0000)}; + static wchar_t const o_m_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x043C),wchar_t(0x0000)}; + static wchar_t const io_m_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x043C),wchar_t(0x0000)}; + static wchar_t const ie_m_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x043C),wchar_t(0x0000)}; + static wchar_t const soft_End[] = { wchar_t(1), wchar_t(0x044C),wchar_t(0x0000)}; + static wchar_t const j_End[] = { wchar_t(1), wchar_t(0x0439),wchar_t(0x0000)}; + + static wchar_t const* const dropEnds[6][8] = { + { &a_End[1], &o_End[1], &ya_End[1], &ie_End[1], &soft_End[1], &j_End[1], NULL, NULL }, + { &a_End[1], &ya_End[1], &yeru_End[1], &i_End[1], NULL, NULL, NULL, NULL }, + { &ie_End[1], &u_End[1], &yu_End[1], &i_End[1], NULL, NULL, NULL, NULL }, + { &u_End[1], &yu_End[1], &o_End[1], &ie_End[1], &soft_End[1], &ya_End[1], &a_End[1], NULL }, + { &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 }, + { &ie_End[1], &i_End[1], NULL, NULL, NULL, NULL, NULL, NULL } + }; + + for(wchar_t const * const* itr = &dropEnds[declension][0]; *itr; ++itr) + { + size_t len = size_t((*itr)[-1]); // get length from string size field + + if(wname.substr(wname.size()-len,len)==*itr) + return wname.substr(0,wname.size()-len); + } + + return wname; +} + +bool utf8ToConsole(std::string utf8str, std::string& conStr) +{ +#if PLATFORM == PLATFORM_WINDOWS + std::wstring wstr; + if(!Utf8toWStr(utf8str,wstr)) + return false; + + conStr.resize(wstr.size()); + CharToOemBuffW(&wstr[0],&conStr[0],wstr.size()); +#else + // not implemented yet + conStr = utf8str; +#endif + + return true; +} + +bool consoleToUtf8(std::string conStr,std::string& utf8str) +{ +#if PLATFORM == PLATFORM_WINDOWS + std::wstring wstr; + wstr.resize(conStr.size()); + OemToCharBuffW(&conStr[0],&wstr[0],conStr.size()); + + return WStrToUtf8(wstr,utf8str); +#else + // not implemented yet + utf8str = conStr; + return true; +#endif +} + +bool Utf8FitTo(std::string str, std::wstring search) +{ + std::wstring temp; + + if(!Utf8toWStr(str,temp)) + return false; + + // converting to lower case + wstrToLower( temp ); + + if(temp.find(search) == std::wstring::npos) + return false; + + return true; +} |