24#include <boost/core/demangle.hpp>
34#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
35 auto isWindowsBuildGreaterOrEqual = [](DWORD build)
37 OSVERSIONINFOEX osvi = {
sizeof(osvi), 0, 0, build, 0, {0}, 0, 0, 0, 0 };
38 ULONGLONG conditionMask = 0;
39 VER_SET_CONDITION(conditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
41 return VerifyVersionInfo(&osvi, VER_BUILDNUMBER, conditionMask);
44 if (!isWindowsBuildGreaterOrEqual(TRINITY_REQUIRED_WINDOWS_BUILD))
46 OSVERSIONINFOEX osvi = {
sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0, 0, 0 };
47 GetVersionEx((LPOSVERSIONINFO)&osvi);
48 ABORT_MSG(
"TrinityCore requires Windows 10 19H1 (1903) or Windows Server 2019 (1903) - require build number 10.0.%d but found %d.%d.%d",
49 TRINITY_REQUIRED_WINDOWS_BUILD, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber);
54std::vector<std::string_view>
Trinity::Tokenize(std::string_view str,
char sep,
bool keepEmpty)
56 std::vector<std::string_view> tokens;
59 for (
size_t end = str.find(sep); end != std::string_view::npos; end = str.find(sep, start))
61 if (keepEmpty || (start < end))
62 tokens.push_back(str.substr(start, end - start));
66 if (keepEmpty || (start < str.length()))
67 tokens.push_back(str.substr(start));
72#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
73struct tm* localtime_r(time_t
const* time,
struct tm *result)
75 if (localtime_s(result, time) != 0)
79struct tm* gmtime_r(time_t
const* time,
struct tm* result)
81 if (gmtime_s(result, time) != 0)
85time_t timegm(
struct tm* tm)
94 localtime_r(&time, &timeLocal);
101 timeLocal.tm_hour = 0;
102 timeLocal.tm_min = 0;
103 timeLocal.tm_sec = 0;
104 time_t midnightLocal = mktime(&timeLocal);
105 time_t hourLocal = midnightLocal + hour *
HOUR;
107 if (onlyAfterTime && hourLocal <= time)
135 std::back_insert_iterator<std::string> itr = std::back_inserter(result);
138 if (hours || hoursOnly)
144 if (secs || result.empty())
150 auto formatTimeField = [](std::string& result,
uint64 value, std::string_view label)
153 result.append(1,
' ');
156 result.append(1,
's');
159 formatTimeField(result, days,
"Day");
160 if (hours || hoursOnly)
161 formatTimeField(result, hours,
"Hour");
165 formatTimeField(result, minutes,
"Minute");
166 if (secs || result.empty())
167 formatTimeField(result, secs,
"Second");
169 result.append(1,
'.');
172 result =
"<Unknown time format>";
188 switch (token[token.length() - 1])
191 if (hadG)
return std::nullopt;
196 if (hadS)
return std::nullopt;
201 if (hadC)
return std::nullopt;
209 Optional<uint64> amount = Trinity::StringTo<uint32>(token.substr(0, token.length() - 1));
211 money += (unit * *amount);
225 for (
char itr : timestring)
236 case 'd': multiplier =
DAY;
break;
237 case 'h': multiplier =
HOUR;
break;
238 case 'm': multiplier =
MINUTE;
break;
239 case 's': multiplier = 1;
break;
242 buffer *= multiplier;
254 localtime_r(&t, &aTm);
261 return Trinity::StringFormat(
"{:04}-{:02}-{:02}_{:02}-{:02}-{:02}", aTm.tm_year + 1900, aTm.tm_mon + 1, aTm.tm_mday, aTm.tm_hour, aTm.tm_min, aTm.tm_sec);
267 localtime_r(&t, &time);
269 strftime(buf, 30,
"%c", &time);
270 return std::string(buf);
279 boost::system::error_code error;
280 Trinity::Net::make_address(ipaddress, error);
287 FILE* pid_file = fopen(filename.c_str(),
"w");
288 if (pid_file ==
nullptr)
293 fprintf(pid_file,
"%u", pid);
302 DWORD pid = GetCurrentProcessId();
304 pid_t pid = getpid();
314 return utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size());
316 catch (std::exception
const&)
327 size_t wlen = utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size());
333 utf8::utf8to16(utf8str.c_str(), utf8str.c_str()+utf8str.size(), &wstr[0]);
335 char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str()+wstr.size(), &utf8str[0]);
336 utf8str.resize(oend-(&utf8str[0]));
338 catch (std::exception
const&)
344bool Utf8toWStr(
char const* utf8str,
size_t csize,
wchar_t* wstr,
size_t& wsize)
349 out = utf8::utf8to16(utf8str, utf8str+csize, out);
353 catch (std::exception
const&)
357 wchar_t const* errorMessage = L
"An error occurred converting string from UTF-8 to WStr";
358 size_t errorMessageLength = wcslen(errorMessage);
359 if (wsize >= errorMessageLength)
361 wcscpy(wstr, errorMessage);
362 wsize = wcslen(wstr);
383 utf8::utf8to16(utf8str.begin(), utf8str.end(), std::back_inserter(wstr));
385 catch (std::exception
const&)
398 std::string utf8str2;
399 utf8str2.resize(
size*4);
403 char* oend = utf8::utf16to8(wstr, wstr+
size, &utf8str2[0]);
404 utf8str2.resize(oend-(&utf8str2[0]));
408 catch (std::exception
const&)
421 std::string utf8str2;
422 utf8str2.resize(wstr.size()*4);
426 char* oend = utf8::utf16to8(wstr.begin(), wstr.end(), &utf8str2[0]);
427 utf8str2.resize(oend-(&utf8str2[0]));
431 catch (std::exception
const&)
448 result.reserve(wstr.length() * 2);
453 for (
wchar_t wchar : wstr)
508 for (
wchar_t wchar : wstr)
523 for (
wchar_t wchar : wstr)
554 for (
wchar_t wchar : wstr)
560 result += wchar_t(0x435);
572 for (
wchar_t wchar : wstr)
632 std::wstring result = wname;
639 static constexpr std::wstring_view a_End = L
"\x430";
640 static constexpr std::wstring_view o_End = L
"\x43E";
641 static constexpr std::wstring_view ya_End = L
"\x44F";
642 static constexpr std::wstring_view ie_End = L
"\x435";
643 static constexpr std::wstring_view i_End = L
"\x438";
644 static constexpr std::wstring_view yeru_End = L
"\x44B";
645 static constexpr std::wstring_view u_End = L
"\x443";
646 static constexpr std::wstring_view yu_End = L
"\x44E";
647 static constexpr std::wstring_view oj_End = L
"\x43E\x439";
648 static constexpr std::wstring_view ie_j_End = L
"\x435\x439";
649 static constexpr std::wstring_view io_j_End = L
"\x451\x439";
650 static constexpr std::wstring_view o_m_End = L
"\x43E\x43C";
651 static constexpr std::wstring_view io_m_End = L
"\x451\x43C";
652 static constexpr std::wstring_view ie_m_End = L
"\x435\x43C";
653 static constexpr std::wstring_view soft_End = L
"\x44C";
654 static constexpr std::wstring_view j_End = L
"\x439";
656 static constexpr std::array<std::array<std::wstring_view, 7>, 6> dropEnds = {{
657 { a_End, o_End, ya_End, ie_End, soft_End, j_End, {} },
658 { a_End, ya_End, yeru_End, i_End, {}, {}, {} },
659 { ie_End, u_End, yu_End, i_End, {}, {}, {} },
660 { u_End, yu_End, o_End, ie_End, soft_End, ya_End, a_End },
661 { oj_End, io_j_End, ie_j_End, o_m_End, io_m_End, ie_m_End, yu_End },
662 { ie_End, i_End, {}, {}, {}, {}, {} }
665 std::size_t
const thisLen = wname.length();
666 std::array<std::wstring_view, 7>
const& endings = dropEnds[declension];
667 for (
auto itr = endings.begin(), end = endings.end(); itr != end && !itr->empty(); ++itr)
669 std::size_t
const endLen = itr->length();
670 if (endLen > thisLen)
673 if (wname.ends_with(*itr))
675 result.erase(thisLen - endLen);
685#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
690 conStr.resize(wstr.size());
691 CharToOemBuffW(&wstr[0], &conStr[0],
uint32(wstr.size()));
702#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
704 wstr.resize(conStr.size());
705 OemToCharBuffW(&conStr[0], &wstr[0],
uint32(conStr.size()));
715bool Utf8FitTo(std::string_view str, std::wstring_view search)
725 if (temp.find(search) == std::wstring::npos)
741#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
742 char temp_buf[32 * 1024];
743 wchar_t wtemp_buf[32 * 1024];
745 size_t temp_len = vsnprintf(temp_buf, 32 * 1024, str, *ap);
747 if (temp_len ==
size_t(-1))
748 temp_len = 32*1024-1;
750 size_t wtemp_len = 32*1024-1;
751 Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len);
753 CharToOemBuffW(&wtemp_buf[0], &temp_buf[0],
uint32(wtemp_len + 1));
754 fprintf(out,
"%s", temp_buf);
756 vfprintf(out, str, *ap);
771#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
774 wchar_t* commandbuf =
new wchar_t[
size + 1];
775 HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
778 if (!ReadConsoleW(hConsole, commandbuf,
size, &read,
nullptr) || read == 0)
784 commandbuf[read] = 0;
786 bool ok =
WStrToUtf8(commandbuf, wcslen(commandbuf), str);
794 wstr.reserve(str.length());
798 HANDLE hConsole = GetStdHandle(error ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE);
801 return WriteConsoleW(hConsole, wstr.c_str(), wstr.size(), &write,
nullptr);
807 std::size_t nextLineIndex = str.find_first_of(
"\r\n");
808 if (nextLineIndex == std::string::npos)
811 str.erase(nextLineIndex);
812 return nextLineIndex;
818 int32 end = arrayLen;
829 result.reserve(arrayLen * 2);
830 auto inserter = std::back_inserter(result);
831 for (
int32 i = init; i != end; i += op)
839 ASSERT(str.size() == (2 * outlen));
847 init =
int32(str.length() - 2);
853 for (
int32 i = init; i != end; i += 2 * op)
854 out[j++] = Trinity::StringTo<uint8>(str.substr(i, 2), 16).value_or(0);
864 return haystack.end() !=
865 std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), [](
char c1,
char c2) { return charToLower(c1) == charToLower(c2); });
875 return boost::core::demangle(info.name());
880 return degrees * (2.f * float(
M_PI) / 360.f);
std::optional< T > Optional
Optional helper class to wrap optional values within.
float DegToRad(float degrees)
bool consoleToUtf8(std::string_view conStr, std::string &utf8str)
std::wstring GetMainPartOfName(std::wstring const &wname, uint32 declension)
bool StringEqualI(std::string_view a, std::string_view b)
bool WriteWinConsole(std::string_view str, bool error)
bool WStrToUtf8(wchar_t const *wstr, size_t size, std::string &utf8str)
bool Utf8ToUpperOnlyLatin(std::string &utf8String)
void wstrToLower(std::wstring &str)
bool IsIPAddress(char const *ipaddress)
Check if the string is a valid ip address representation.
std::string TimeToTimestampStr(time_t t)
bool StringContainsStringI(std::string_view haystack, std::string_view needle)
time_t GetLocalHourTimestamp(time_t time, uint8 hour, bool onlyAfterTime)
void utf8printf(FILE *out, const char *str,...)
void strToLower(std::string &str)
TC_COMMON_API Optional< std::size_t > RemoveCRLF(std::string &str)
uint32 CreatePIDFile(std::string const &filename)
create PID file
bool utf8ToConsole(std::string_view utf8str, std::string &conStr)
tm TimeBreakdown(time_t time)
std::wstring wstrCaseAccentInsensitiveParse(std::wstring_view wstr, LocaleConstant locale)
std::string TimeToHumanReadable(time_t t)
bool StringCompareLessI(std::string_view a, std::string_view b)
bool Utf8FitTo(std::string_view str, std::wstring_view search)
std::string secsToTimeString(uint64 timeInSecs, TimeFormat timeFormat, bool hoursOnly)
bool Utf8toWStr(char const *utf8str, size_t csize, wchar_t *wstr, size_t &wsize)
Optional< int64 > MoneyStringToMoney(std::string const &moneyString)
bool ReadWinConsole(std::string &str, size_t size)
size_t utf8length(std::string &utf8str)
void utf8truncate(std::string &utf8str, size_t len)
uint32 TimeStringToSecs(std::string const ×tring)
void wstrToUpper(std::wstring &str)
void strToUpper(std::string &str)
void vutf8printf(FILE *out, const char *str, va_list *ap)
struct WcharToUpperOnlyLatin wcharToUpperOnlyLatin
struct WcharToLower wcharToLower
struct CharToUpper charToUpper
bool isCyrillicCharacter(wchar_t wchar)
struct CharToLower charToLower
struct WcharToUpper wcharToUpper
TC_COMMON_API void HexStrToByteArray(std::string_view str, uint8 *out, size_t outlen, bool reverse=false)
TC_COMMON_API std::string ByteArrayToHexStr(uint8 const *bytes, size_t length, bool reverse=false)
TC_COMMON_API std::string GetTypeName(std::type_info const &)
TC_COMMON_API void VerifyOsVersion()
TC_COMMON_API std::vector< std::string_view > Tokenize(std::string_view str, char sep, bool keepEmpty)
OutputIt StringFormatTo(OutputIt out, FormatString< Args... > fmt, Args &&... args)
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
constexpr std::size_t size()