23#include <boost/core/demangle.hpp>
31#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
37#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
38 auto isWindowsBuildGreaterOrEqual = [](DWORD build)
40 OSVERSIONINFOEX osvi = {
sizeof(osvi), 0, 0, build, 0, {0}, 0, 0, 0, 0 };
41 ULONGLONG conditionMask = 0;
42 VER_SET_CONDITION(conditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
44 return VerifyVersionInfo(&osvi, VER_BUILDNUMBER, conditionMask);
47 if (!isWindowsBuildGreaterOrEqual(TRINITY_REQUIRED_WINDOWS_BUILD))
49 OSVERSIONINFOEX osvi = {
sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0, 0, 0 };
50 GetVersionEx((LPOSVERSIONINFO)&osvi);
51 ABORT_MSG(
"TrinityCore requires Windows 10 19H1 (1903) or Windows Server 2019 (1903) - require build number 10.0.%d but found %d.%d.%d",
52 TRINITY_REQUIRED_WINDOWS_BUILD, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber);
57std::vector<std::string_view>
Trinity::Tokenize(std::string_view str,
char sep,
bool keepEmpty)
59 std::vector<std::string_view> tokens;
62 for (
size_t end = str.find(sep); end != std::string_view::npos; end = str.find(sep, start))
64 if (keepEmpty || (start < end))
65 tokens.push_back(str.substr(start, end - start));
69 if (keepEmpty || (start < str.length()))
70 tokens.push_back(str.substr(start));
75#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
76struct tm* localtime_r(time_t
const* time,
struct tm *result)
78 if (localtime_s(result, time) != 0)
82struct tm* gmtime_r(time_t
const* time,
struct tm* result)
84 if (gmtime_s(result, time) != 0)
88time_t timegm(
struct tm* tm)
97 localtime_r(&time, &timeLocal);
104 timeLocal.tm_hour = 0;
105 timeLocal.tm_min = 0;
106 timeLocal.tm_sec = 0;
107 time_t midnightLocal = mktime(&timeLocal);
108 time_t hourLocal = midnightLocal + hour *
HOUR;
110 if (onlyAfterTime && hourLocal <= time)
138 std::back_insert_iterator<std::string> itr = std::back_inserter(result);
141 if (hours || hoursOnly)
147 if (secs || result.empty())
153 auto formatTimeField = [](std::string& result,
uint64 value, std::string_view label)
156 result.append(1,
' ');
159 result.append(1,
's');
162 formatTimeField(result, days,
"Day");
163 if (hours || hoursOnly)
164 formatTimeField(result, hours,
"Hour");
168 formatTimeField(result, minutes,
"Minute");
169 if (secs || result.empty())
170 formatTimeField(result, secs,
"Second");
172 result.append(1,
'.');
175 result =
"<Unknown time format>";
191 switch (token[token.length() - 1])
194 if (hadG)
return std::nullopt;
199 if (hadS)
return std::nullopt;
204 if (hadC)
return std::nullopt;
212 Optional<uint64> amount = Trinity::StringTo<uint32>(token.substr(0, token.length() - 1));
214 money += (unit * *amount);
228 for (
char itr : timestring)
239 case 'd': multiplier =
DAY;
break;
240 case 'h': multiplier =
HOUR;
break;
241 case 'm': multiplier =
MINUTE;
break;
242 case 's': multiplier = 1;
break;
245 buffer *= multiplier;
257 localtime_r(&t, &aTm);
264 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);
270 localtime_r(&t, &time);
272 strftime(buf, 30,
"%c", &time);
273 return std::string(buf);
279 FILE* pid_file = fopen(filename.c_str(),
"w");
280 if (pid_file ==
nullptr)
285 fprintf(pid_file,
"%u", pid);
294 DWORD pid = GetCurrentProcessId();
296 pid_t pid = getpid();
306 return utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size());
308 catch (std::exception
const&)
319 size_t wlen = utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size());
325 utf8::utf8to16(utf8str.c_str(), utf8str.c_str()+utf8str.size(), &wstr[0]);
327 char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str()+wstr.size(), &utf8str[0]);
328 utf8str.resize(oend-(&utf8str[0]));
330 catch (std::exception
const&)
336bool Utf8toWStr(
char const* utf8str,
size_t csize,
wchar_t* wstr,
size_t& wsize)
341 out = utf8::utf8to16(utf8str, utf8str+csize, out);
345 catch (std::exception
const&)
349 wchar_t const* errorMessage = L
"An error occurred converting string from UTF-8 to WStr";
350 size_t errorMessageLength = wcslen(errorMessage);
351 if (wsize >= errorMessageLength)
353 wcscpy(wstr, errorMessage);
354 wsize = wcslen(wstr);
375 utf8::utf8to16(utf8str.begin(), utf8str.end(), std::back_inserter(wstr));
377 catch (std::exception
const&)
386bool WStrToUtf8(
wchar_t const* wstr,
size_t size, std::string& utf8str)
390 std::string utf8str2;
391 utf8str2.resize(size*4);
395 char* oend = utf8::utf16to8(wstr, wstr+size, &utf8str2[0]);
396 utf8str2.resize(oend-(&utf8str2[0]));
400 catch (std::exception
const&)
413 std::string utf8str2;
414 utf8str2.resize(wstr.size()*4);
418 char* oend = utf8::utf16to8(wstr.begin(), wstr.end(), &utf8str2[0]);
419 utf8str2.resize(oend-(&utf8str2[0]));
423 catch (std::exception
const&)
440 result.reserve(wstr.length() * 2);
445 for (
wchar_t wchar : wstr)
500 for (
wchar_t wchar : wstr)
515 for (
wchar_t wchar : wstr)
546 for (
wchar_t wchar : wstr)
552 result += wchar_t(0x435);
564 for (
wchar_t wchar : wstr)
624 std::wstring result = wname;
631 static constexpr std::wstring_view a_End = L
"\x430";
632 static constexpr std::wstring_view o_End = L
"\x43E";
633 static constexpr std::wstring_view ya_End = L
"\x44F";
634 static constexpr std::wstring_view ie_End = L
"\x435";
635 static constexpr std::wstring_view i_End = L
"\x438";
636 static constexpr std::wstring_view yeru_End = L
"\x44B";
637 static constexpr std::wstring_view u_End = L
"\x443";
638 static constexpr std::wstring_view yu_End = L
"\x44E";
639 static constexpr std::wstring_view oj_End = L
"\x43E\x439";
640 static constexpr std::wstring_view ie_j_End = L
"\x435\x439";
641 static constexpr std::wstring_view io_j_End = L
"\x451\x439";
642 static constexpr std::wstring_view o_m_End = L
"\x43E\x43C";
643 static constexpr std::wstring_view io_m_End = L
"\x451\x43C";
644 static constexpr std::wstring_view ie_m_End = L
"\x435\x43C";
645 static constexpr std::wstring_view soft_End = L
"\x44C";
646 static constexpr std::wstring_view j_End = L
"\x439";
648 static constexpr std::array<std::array<std::wstring_view, 7>, 6> dropEnds = {{
649 { a_End, o_End, ya_End, ie_End, soft_End, j_End, {} },
650 { a_End, ya_End, yeru_End, i_End, {}, {}, {} },
651 { ie_End, u_End, yu_End, i_End, {}, {}, {} },
652 { u_End, yu_End, o_End, ie_End, soft_End, ya_End, a_End },
653 { oj_End, io_j_End, ie_j_End, o_m_End, io_m_End, ie_m_End, yu_End },
654 { ie_End, i_End, {}, {}, {}, {}, {} }
657 std::size_t
const thisLen = wname.length();
658 std::array<std::wstring_view, 7>
const& endings = dropEnds[declension];
659 for (
auto itr = endings.begin(), end = endings.end(); itr != end && !itr->empty(); ++itr)
661 std::size_t
const endLen = itr->length();
662 if (endLen > thisLen)
665 if (wname.ends_with(*itr))
667 result.erase(thisLen - endLen);
677#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
682 conStr.resize(wstr.size());
683 CharToOemBuffW(&wstr[0], &conStr[0],
uint32(wstr.size()));
694#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
696 wstr.resize(conStr.size());
697 OemToCharBuffW(&conStr[0], &wstr[0],
uint32(conStr.size()));
707bool Utf8FitTo(std::string_view str, std::wstring_view search)
717 if (temp.find(search) == std::wstring::npos)
733#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
734 char temp_buf[32 * 1024];
735 wchar_t wtemp_buf[32 * 1024];
737 size_t temp_len = vsnprintf(temp_buf, 32 * 1024, str, *ap);
739 if (temp_len ==
size_t(-1))
740 temp_len = 32*1024-1;
742 size_t wtemp_len = 32*1024-1;
743 Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len);
745 CharToOemBuffW(&wtemp_buf[0], &temp_buf[0],
uint32(wtemp_len + 1));
746 fprintf(out,
"%s", temp_buf);
748 vfprintf(out, str, *ap);
763#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
766 wchar_t* commandbuf =
new wchar_t[size + 1];
767 HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
770 if (!ReadConsoleW(hConsole, commandbuf, size, &read,
nullptr) || read == 0)
776 commandbuf[read] = 0;
778 bool ok =
WStrToUtf8(commandbuf, wcslen(commandbuf), str);
786 wstr.reserve(str.length());
790 HANDLE hConsole = GetStdHandle(error ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE);
793 return WriteConsoleW(hConsole, wstr.c_str(), wstr.size(), &write,
nullptr);
799 std::size_t nextLineIndex = str.find_first_of(
"\r\n");
800 if (nextLineIndex == std::string::npos)
803 str.erase(nextLineIndex);
804 return nextLineIndex;
810 int32 end = arrayLen;
821 result.resize(arrayLen * 2);
822 auto inserter = result.data();
823 for (
int32 i = init; i != end; i += op)
831 ASSERT(str.size() == (2 * outlen));
839 init =
int32(str.length() - 2);
845 for (
int32 i = init; i != end; i += 2 * op)
846 out[j++] = Trinity::StringTo<uint8>(str.substr(i, 2), 16).value_or(0);
856 return haystack.end() !=
857 std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), [](
char c1,
char c2) { return charToLower(c1) == charToLower(c2); });
865void StringReplaceAll(std::string* str, std::string_view text, std::string_view replacement)
867 std::size_t pos = str->find(text, 0);
868 while (pos != std::string::npos)
870 str->replace(pos, text.length(), replacement);
871 pos = str->find(text, pos + replacement.length());
877 return boost::core::demangle(info.name());
882 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)
std::string TimeToTimestampStr(time_t t)
void StringReplaceAll(std::string *str, std::string_view text, std::string_view replacement)
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) noexcept
std::string StringFormat(FormatString< Args... > fmt, Args &&... args) noexcept
Default TC string format function.