TrinityCore
Util.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "Util.h"
19#include "Common.h"
20#include "Containers.h"
21#include "IpAddress.h"
22#include "StringConvert.h"
23#include "StringFormat.h"
24#include <boost/core/demangle.hpp>
25#include <utf8.h>
26#include <algorithm>
27#include <iomanip>
28#include <sstream>
29#include <string>
30#include <cctype>
31#include <cstdarg>
32#include <ctime>
33
35{
36#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
37 auto isWindowsBuildGreaterOrEqual = [](DWORD build)
38 {
39 OSVERSIONINFOEX osvi = { sizeof(osvi), 0, 0, build, 0, {0}, 0, 0, 0, 0 };
40 ULONGLONG conditionMask = 0;
41 VER_SET_CONDITION(conditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
42
43 return VerifyVersionInfo(&osvi, VER_BUILDNUMBER, conditionMask);
44 };
45
46 if (!isWindowsBuildGreaterOrEqual(TRINITY_REQUIRED_WINDOWS_BUILD))
47 {
48 OSVERSIONINFOEX osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0, 0, 0 };
49 GetVersionEx((LPOSVERSIONINFO)&osvi);
50 ABORT_MSG("TrinityCore requires Windows 10 19H1 (1903) or Windows Server 2019 (1903) - require build number 10.0.%d but found %d.%d.%d",
51 TRINITY_REQUIRED_WINDOWS_BUILD, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber);
52 }
53#endif
54}
55
56std::vector<std::string_view> Trinity::Tokenize(std::string_view str, char sep, bool keepEmpty)
57{
58 std::vector<std::string_view> tokens;
59
60 size_t start = 0;
61 for (size_t end = str.find(sep); end != std::string_view::npos; end = str.find(sep, start))
62 {
63 if (keepEmpty || (start < end))
64 tokens.push_back(str.substr(start, end - start));
65 start = end+1;
66 }
67
68 if (keepEmpty || (start < str.length()))
69 tokens.push_back(str.substr(start));
70
71 return tokens;
72}
73
74#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
75struct tm* localtime_r(time_t const* time, struct tm *result)
76{
77 if (localtime_s(result, time) != 0)
78 return nullptr;
79 return result;
80}
81struct tm* gmtime_r(time_t const* time, struct tm* result)
82{
83 if (gmtime_s(result, time) != 0)
84 return nullptr;
85 return result;
86}
87time_t timegm(struct tm* tm)
88{
89 return _mkgmtime(tm);
90}
91#endif
92
93tm TimeBreakdown(time_t time)
94{
95 tm timeLocal;
96 localtime_r(&time, &timeLocal);
97 return timeLocal;
98}
99
100time_t GetLocalHourTimestamp(time_t time, uint8 hour, bool onlyAfterTime)
101{
102 tm timeLocal = TimeBreakdown(time);
103 timeLocal.tm_hour = 0;
104 timeLocal.tm_min = 0;
105 timeLocal.tm_sec = 0;
106 time_t midnightLocal = mktime(&timeLocal);
107 time_t hourLocal = midnightLocal + hour * HOUR;
108
109 if (onlyAfterTime && hourLocal <= time)
110 hourLocal += DAY;
111
112 return hourLocal;
113}
114
115std::string secsToTimeString(uint64 timeInSecs, TimeFormat timeFormat, bool hoursOnly)
116{
117 uint64 secs = timeInSecs % MINUTE;
118 uint64 minutes = timeInSecs % HOUR / MINUTE;
119 uint64 hours = timeInSecs % DAY / HOUR;
120 uint64 days = timeInSecs / DAY;
121
122 if (timeFormat == TimeFormat::Numeric)
123 {
124 if (days)
125 return Trinity::StringFormat("{}:{:02}:{:02}:{:02}", days, hours, minutes, secs);
126 else if (hours)
127 return Trinity::StringFormat("{}:{:02}:{:02}", hours, minutes, secs);
128 else if (minutes)
129 return Trinity::StringFormat("{}:{:02}", minutes, secs);
130 else
131 return Trinity::StringFormat("0:{:02}", secs);
132 }
133
134 std::ostringstream ss;
135 if (days)
136 {
137 ss << days;
138 switch (timeFormat)
139 {
141 ss << "d";
142 break;
144 if (days == 1)
145 ss << " Day ";
146 else
147 ss << " Days ";
148 break;
149 default:
150 return "<Unknown time format>";
151 }
152 }
153
154 if (hours || hoursOnly)
155 {
156 ss << hours;
157 switch (timeFormat)
158 {
160 ss << "h";
161 break;
163 if (hours <= 1)
164 ss << " Hour ";
165 else
166 ss << " Hours ";
167 break;
168 default:
169 return "<Unknown time format>";
170 }
171 }
172 if (!hoursOnly)
173 {
174 if (minutes)
175 {
176 ss << minutes;
177 switch (timeFormat)
178 {
180 ss << "m";
181 break;
183 if (minutes == 1)
184 ss << " Minute ";
185 else
186 ss << " Minutes ";
187 break;
188 default:
189 return "<Unknown time format>";
190 }
191 }
192
193 if (secs || (!days && !hours && !minutes))
194 {
195 ss << secs;
196 switch (timeFormat)
197 {
199 ss << "s";
200 break;
202 if (secs <= 1)
203 ss << " Second.";
204 else
205 ss << " Seconds.";
206 break;
207 default:
208 return "<Unknown time format>";
209 }
210 }
211 }
212
213 return ss.str();
214}
215
216Optional<int64> MoneyStringToMoney(std::string const& moneyString)
217{
218 int64 money = 0;
219
220 bool hadG = false;
221 bool hadS = false;
222 bool hadC = false;
223
224 for (std::string_view token : Trinity::Tokenize(moneyString, ' ', false))
225 {
226 uint32 unit;
227 switch (token[token.length() - 1])
228 {
229 case 'g':
230 if (hadG) return std::nullopt;
231 hadG = true;
232 unit = 100 * 100;
233 break;
234 case 's':
235 if (hadS) return std::nullopt;
236 hadS = true;
237 unit = 100;
238 break;
239 case 'c':
240 if (hadC) return std::nullopt;
241 hadC = true;
242 unit = 1;
243 break;
244 default:
245 return std::nullopt;
246 }
247
248 Optional<uint64> amount = Trinity::StringTo<uint32>(token.substr(0, token.length() - 1));
249 if (amount)
250 money += (unit * *amount);
251 else
252 return std::nullopt;
253 }
254
255 return money;
256}
257
258uint32 TimeStringToSecs(std::string const& timestring)
259{
260 uint32 secs = 0;
261 uint32 buffer = 0;
262 uint32 multiplier = 0;
263
264 for (char itr : timestring)
265 {
266 if (isdigit(itr))
267 {
268 buffer *= 10;
269 buffer += itr - '0';
270 }
271 else
272 {
273 switch (itr)
274 {
275 case 'd': multiplier = DAY; break;
276 case 'h': multiplier = HOUR; break;
277 case 'm': multiplier = MINUTE; break;
278 case 's': multiplier = 1; break;
279 default : return 0; //bad format
280 }
281 buffer *= multiplier;
282 secs += buffer;
283 buffer = 0;
284 }
285 }
286
287 return secs;
288}
289
290std::string TimeToTimestampStr(time_t t)
291{
292 tm aTm;
293 localtime_r(&t, &aTm);
294 // YYYY year
295 // MM month (2 digits 01-12)
296 // DD day (2 digits 01-31)
297 // HH hour (2 digits 00-23)
298 // MM minutes (2 digits 00-59)
299 // SS seconds (2 digits 00-59)
300 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);
301}
302
303std::string TimeToHumanReadable(time_t t)
304{
305 tm time;
306 localtime_r(&t, &time);
307 char buf[30];
308 strftime(buf, 30, "%c", &time);
309 return std::string(buf);
310}
311
313bool IsIPAddress(char const* ipaddress)
314{
315 if (!ipaddress)
316 return false;
317
318 boost::system::error_code error;
319 Trinity::Net::make_address(ipaddress, error);
320 return !error;
321}
322
324uint32 CreatePIDFile(std::string const& filename)
325{
326 FILE* pid_file = fopen(filename.c_str(), "w");
327 if (pid_file == nullptr)
328 return 0;
329
330 uint32 pid = GetPID();
331
332 fprintf(pid_file, "%u", pid);
333 fclose(pid_file);
334
335 return pid;
336}
337
339{
340#ifdef _WIN32
341 DWORD pid = GetCurrentProcessId();
342#else
343 pid_t pid = getpid();
344#endif
345
346 return uint32(pid);
347}
348
349size_t utf8length(std::string& utf8str)
350{
351 try
352 {
353 return utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size());
354 }
355 catch (std::exception const&)
356 {
357 utf8str.clear();
358 return 0;
359 }
360}
361
362void utf8truncate(std::string& utf8str, size_t len)
363{
364 try
365 {
366 size_t wlen = utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size());
367 if (wlen <= len)
368 return;
369
370 std::wstring wstr;
371 wstr.resize(wlen);
372 utf8::utf8to16(utf8str.c_str(), utf8str.c_str()+utf8str.size(), &wstr[0]);
373 wstr.resize(len);
374 char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str()+wstr.size(), &utf8str[0]);
375 utf8str.resize(oend-(&utf8str[0])); // remove unused tail
376 }
377 catch (std::exception const&)
378 {
379 utf8str.clear();
380 }
381}
382
383bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize)
384{
385 try
386 {
388 out = utf8::utf8to16(utf8str, utf8str+csize, out);
389 wsize -= out.remaining(); // remaining unused space
390 wstr[wsize] = L'\0';
391 }
392 catch (std::exception const&)
393 {
394 // Replace the converted string with an error message if there is enough space
395 // Otherwise just return an empty string
396 wchar_t const* errorMessage = L"An error occurred converting string from UTF-8 to WStr";
397 size_t errorMessageLength = wcslen(errorMessage);
398 if (wsize >= errorMessageLength)
399 {
400 wcscpy(wstr, errorMessage);
401 wsize = wcslen(wstr);
402 }
403 else if (wsize > 0)
404 {
405 wstr[0] = L'\0';
406 wsize = 0;
407 }
408 else
409 wsize = 0;
410
411 return false;
412 }
413
414 return true;
415}
416
417bool Utf8toWStr(std::string_view utf8str, std::wstring& wstr)
418{
419 wstr.clear();
420 try
421 {
422 utf8::utf8to16(utf8str.begin(), utf8str.end(), std::back_inserter(wstr));
423 }
424 catch (std::exception const&)
425 {
426 wstr.clear();
427 return false;
428 }
429
430 return true;
431}
432
433bool WStrToUtf8(wchar_t const* wstr, size_t size, std::string& utf8str)
434{
435 try
436 {
437 std::string utf8str2;
438 utf8str2.resize(size*4); // allocate for most long case
439
440 if (size)
441 {
442 char* oend = utf8::utf16to8(wstr, wstr+size, &utf8str2[0]);
443 utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail
444 }
445 utf8str = utf8str2;
446 }
447 catch (std::exception const&)
448 {
449 utf8str.clear();
450 return false;
451 }
452
453 return true;
454}
455
456bool WStrToUtf8(std::wstring_view wstr, std::string& utf8str)
457{
458 try
459 {
460 std::string utf8str2;
461 utf8str2.resize(wstr.size()*4); // allocate for most long case
462
463 if (!wstr.empty())
464 {
465 char* oend = utf8::utf16to8(wstr.begin(), wstr.end(), &utf8str2[0]);
466 utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail
467 }
468 utf8str = utf8str2;
469 }
470 catch (std::exception const&)
471 {
472 utf8str.clear();
473 return false;
474 }
475
476 return true;
477}
478
479void wstrToUpper(std::wstring& str) { std::transform(std::begin(str), std::end(str), std::begin(str), wcharToUpper); }
480void wstrToLower(std::wstring& str) { std::transform(std::begin(str), std::end(str), std::begin(str), wcharToLower); }
481void strToUpper(std::string& str) { std::transform(std::begin(str), std::end(str), std::begin(str), charToUpper); }
482void strToLower(std::string& str) { std::transform(std::begin(str), std::end(str), std::begin(str), charToLower); }
483
484std::wstring wstrCaseAccentInsensitiveParse(std::wstring_view wstr, LocaleConstant locale)
485{
486 std::wstring result;
487 result.reserve(wstr.length() * 2);
488
489 switch (locale)
490 {
491 case LOCALE_frFR:
492 for (wchar_t wchar : wstr)
493 {
494 wchar = wcharToLower(wchar);
495 switch (wchar)
496 {
497 case 0x00A0: // NO-BREAK SPACE
498 result += L' ';
499 break;
500 case 0x00AB: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
501 case 0x00BB: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
502 result += L'"';
503 break;
504 case 0x00E7: // LATIN SMALL LETTER C WITH CEDILLA
505 result += L'c';
506 break;
507 case 0x00E8: // LATIN SMALL LETTER E WITH GRAVE
508 case 0x00E9: // LATIN SMALL LETTER E WITH ACUTE
509 case 0x00EA: // LATIN SMALL LETTER E WITH CIRCUMFLEX
510 case 0x00EB: // LATIN SMALL LETTER E WITH DIAERESIS
511 result += L'e';
512 break;
513 case 0x00EE: // LATIN SMALL LETTER I WITH CIRCUMFLEX
514 case 0x00EF: // LATIN SMALL LETTER I WITH DIAERESIS
515 result += L'i';
516 break;
517 case 0x00F2: // LATIN SMALL LETTER O WITH GRAVE
518 case 0x00F3: // LATIN SMALL LETTER O WITH ACUTE
519 case 0x00F4: // LATIN SMALL LETTER O WITH CIRCUMFLEX
520 case 0x00F6: // LATIN SMALL LETTER O WITH DIAERESIS
521 result += L'o';
522 break;
523 case 0x00F9: // LATIN SMALL LETTER U WITH GRAVE
524 case 0x00FA: // LATIN SMALL LETTER U WITH ACUTE
525 case 0x00FB: // LATIN SMALL LETTER U WITH CIRCUMFLEX
526 case 0x00FC: // LATIN SMALL LETTER U WITH DIAERESIS
527 result += L'u';
528 break;
529 case 0x0153: // LATIN SMALL LIGATURE OE
530 result += L'o';
531 result += L'e';
532 break;
533 case 0x2013: // EN DASH
534 result += L'-';
535 break;
536 case 0x2018: // LEFT SINGLE QUOTATION MARK
537 case 0x2019: // RIGHT SINGLE QUOTATION MARK
538 result += L'\'';
539 break;
540 default:
541 result += wchar;
542 break;
543 }
544 }
545 break;
546 case LOCALE_deDE:
547 for (wchar_t wchar : wstr)
548 {
549 wchar = wcharToLower(wchar);
550 if (wchar == 0x00DF) // LATIN SMALL LETTER SHARP S
551 {
552 result += L's';
553 result += L's';
554 }
555 else
556 result += wchar;
557 }
558 break;
559 case LOCALE_esES:
560 case LOCALE_esMX:
561 case LOCALE_itIT:
562 for (wchar_t wchar : wstr)
563 {
564 wchar = wcharToLower(wchar);
565 switch (wchar)
566 {
567 case 0x00E1: // LATIN SMALL LETTER A WITH ACUTE
568 result += L'a';
569 break;
570 case 0x00E9: // LATIN SMALL LETTER E WITH ACUTE
571 result += L'e';
572 break;
573 case 0x00ED: // LATIN SMALL LETTER I WITH ACUTE
574 result += L'i';
575 break;
576 case 0x00F1: // LATIN SMALL LETTER N WITH TILDE
577 result += L'n';
578 break;
579 case 0x00F3: // LATIN SMALL LETTER O WITH ACUTE
580 result += L'o';
581 break;
582 case 0x00FA: // LATIN SMALL LETTER U WITH ACUTE
583 case 0x00FC: // LATIN SMALL LETTER U WITH DIAERESIS
584 result += L'u';
585 break;
586 default:
587 result += wchar;
588 break;
589 }
590 }
591 break;
592 case LOCALE_ruRU:
593 for (wchar_t wchar : wstr)
594 {
595 wchar = wcharToLower(wchar);
596 switch (wchar)
597 {
598 case 0x451: // CYRILLIC SMALL LETTER IO
599 result += wchar_t(0x435);
600 break;
601 case 0x2013: // EN DASH
602 result += L'-';
603 break;
604 default:
605 result += wchar;
606 break;
607 }
608 }
609 break;
610 case LOCALE_ptBR:
611 for (wchar_t wchar : wstr)
612 {
613 wchar = wcharToLower(wchar);
614 switch (wchar)
615 {
616 case 0x00E0: // LATIN SMALL LETTER A WITH GRAVE
617 case 0x00E1: // LATIN SMALL LETTER A WITH ACUTE
618 case 0x00E2: // LATIN SMALL LETTER A WITH CIRCUMFLEX
619 case 0x00E3: // LATIN SMALL LETTER A WITH TILDE
620 case 0x00E4: // LATIN SMALL LETTER A WITH DIAERESIS
621 result += L'a';
622 break;
623 case 0x00E7: // LATIN SMALL LETTER C WITH CEDILLA
624 result += L'c';
625 break;
626 case 0x00E8: // LATIN SMALL LETTER E WITH GRAVE
627 case 0x00E9: // LATIN SMALL LETTER E WITH ACUTE
628 case 0x00EA: // LATIN SMALL LETTER E WITH CIRCUMFLEX
629 case 0x00EB: // LATIN SMALL LETTER E WITH DIAERESIS
630 result += L'e';
631 break;
632 case 0x00EC: // LATIN SMALL LETTER I WITH GRAVE
633 case 0x00ED: // LATIN SMALL LETTER I WITH ACUTE
634 case 0x00EE: // LATIN SMALL LETTER I WITH CIRCUMFLEX
635 case 0x00EF: // LATIN SMALL LETTER I WITH DIAERESIS
636 result += L'i';
637 break;
638 case 0x00F1: // LATIN SMALL LETTER N WITH TILDE
639 result += L'n';
640 break;
641 case 0x00F2: // LATIN SMALL LETTER O WITH GRAVE
642 case 0x00F3: // LATIN SMALL LETTER O WITH ACUTE
643 case 0x00F4: // LATIN SMALL LETTER O WITH CIRCUMFLEX
644 case 0x00F5: // LATIN SMALL LETTER O WITH TILDE
645 case 0x00F6: // LATIN SMALL LETTER O WITH DIAERESIS
646 result += L'o';
647 break;
648 case 0x00F9: // LATIN SMALL LETTER U WITH GRAVE
649 case 0x00FA: // LATIN SMALL LETTER U WITH ACUTE
650 case 0x00FB: // LATIN SMALL LETTER U WITH CIRCUMFLEX
651 case 0x00FC: // LATIN SMALL LETTER U WITH DIAERESIS
652 result += L'u';
653 break;
654 default:
655 result += wchar;
656 break;
657 }
658 }
659 break;
660 default:
661 result = wstr;
662 wstrToLower(result);
663 break;
664 }
665
666 return result;
667}
668
669std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension)
670{
671 // supported only Cyrillic cases
672 if (wname.empty() || !isCyrillicCharacter(wname[0]) || declension > 5)
673 return wname;
674
675 // Important: end length must be <= MAX_INTERNAL_PLAYER_NAME-MAX_PLAYER_NAME (3 currently)
676 static std::wstring const a_End = { wchar_t(0x0430) };
677 static std::wstring const o_End = { wchar_t(0x043E) };
678 static std::wstring const ya_End = { wchar_t(0x044F) };
679 static std::wstring const ie_End = { wchar_t(0x0435) };
680 static std::wstring const i_End = { wchar_t(0x0438) };
681 static std::wstring const yeru_End = { wchar_t(0x044B) };
682 static std::wstring const u_End = { wchar_t(0x0443) };
683 static std::wstring const yu_End = { wchar_t(0x044E) };
684 static std::wstring const oj_End = { wchar_t(0x043E), wchar_t(0x0439) };
685 static std::wstring const ie_j_End = { wchar_t(0x0435), wchar_t(0x0439) };
686 static std::wstring const io_j_End = { wchar_t(0x0451), wchar_t(0x0439) };
687 static std::wstring const o_m_End = { wchar_t(0x043E), wchar_t(0x043C) };
688 static std::wstring const io_m_End = { wchar_t(0x0451), wchar_t(0x043C) };
689 static std::wstring const ie_m_End = { wchar_t(0x0435), wchar_t(0x043C) };
690 static std::wstring const soft_End = { wchar_t(0x044C) };
691 static std::wstring const j_End = { wchar_t(0x0439) };
692
693 static std::array<std::array<std::wstring const*, 7>, 6> const dropEnds = {{
694 { &a_End, &o_End, &ya_End, &ie_End, &soft_End, &j_End, nullptr },
695 { &a_End, &ya_End, &yeru_End, &i_End, nullptr, nullptr, nullptr },
696 { &ie_End, &u_End, &yu_End, &i_End, nullptr, nullptr, nullptr },
697 { &u_End, &yu_End, &o_End, &ie_End, &soft_End, &ya_End, &a_End },
698 { &oj_End, &io_j_End, &ie_j_End, &o_m_End, &io_m_End, &ie_m_End, &yu_End },
699 { &ie_End, &i_End, nullptr, nullptr, nullptr, nullptr, nullptr }
700 }};
701
702 std::size_t const thisLen = wname.length();
703 std::array<std::wstring const*, 7> const& endings = dropEnds[declension];
704 for (auto itr = endings.begin(), end = endings.end(); (itr != end) && *itr; ++itr)
705 {
706 std::wstring const& ending = **itr;
707 std::size_t const endLen = ending.length();
708 if (!(endLen <= thisLen))
709 continue;
710
711 if (wname.substr(thisLen-endLen, thisLen) == ending)
712 return wname.substr(0, thisLen-endLen);
713 }
714
715 return wname;
716}
717
718bool utf8ToConsole(std::string_view utf8str, std::string& conStr)
719{
720#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
721 std::wstring wstr;
722 if (!Utf8toWStr(utf8str, wstr))
723 return false;
724
725 conStr.resize(wstr.size());
726 CharToOemBuffW(&wstr[0], &conStr[0], uint32(wstr.size()));
727#else
728 // not implemented yet
729 conStr = utf8str;
730#endif
731
732 return true;
733}
734
735bool consoleToUtf8(std::string_view conStr, std::string& utf8str)
736{
737#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
738 std::wstring wstr;
739 wstr.resize(conStr.size());
740 OemToCharBuffW(&conStr[0], &wstr[0], uint32(conStr.size()));
741
742 return WStrToUtf8(wstr, utf8str);
743#else
744 // not implemented yet
745 utf8str = conStr;
746 return true;
747#endif
748}
749
750bool Utf8FitTo(std::string_view str, std::wstring_view search)
751{
752 std::wstring temp;
753
754 if (!Utf8toWStr(str, temp))
755 return false;
756
757 // converting to lower case
758 wstrToLower(temp);
759
760 if (temp.find(search) == std::wstring::npos)
761 return false;
762
763 return true;
764}
765
766void utf8printf(FILE* out, const char *str, ...)
767{
768 va_list ap;
769 va_start(ap, str);
770 vutf8printf(out, str, &ap);
771 va_end(ap);
772}
773
774void vutf8printf(FILE* out, const char *str, va_list* ap)
775{
776#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
777 char temp_buf[32 * 1024];
778 wchar_t wtemp_buf[32 * 1024];
779
780 size_t temp_len = vsnprintf(temp_buf, 32 * 1024, str, *ap);
781 //vsnprintf returns -1 if the buffer is too small
782 if (temp_len == size_t(-1))
783 temp_len = 32*1024-1;
784
785 size_t wtemp_len = 32*1024-1;
786 Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len);
787
788 CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], uint32(wtemp_len + 1));
789 fprintf(out, "%s", temp_buf);
790#else
791 vfprintf(out, str, *ap);
792#endif
793}
794
795bool Utf8ToUpperOnlyLatin(std::string& utf8String)
796{
797 std::wstring wstr;
798 if (!Utf8toWStr(utf8String, wstr))
799 return false;
800
801 std::transform(wstr.begin(), wstr.end(), wstr.begin(), wcharToUpperOnlyLatin);
802
803 return WStrToUtf8(wstr, utf8String);
804}
805
806#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
807bool ReadWinConsole(std::string& str, size_t size /*= 256*/)
808{
809 wchar_t* commandbuf = new wchar_t[size + 1];
810 HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
811 DWORD read = 0;
812
813 if (!ReadConsoleW(hConsole, commandbuf, size, &read, nullptr) || read == 0)
814 {
815 delete[] commandbuf;
816 return false;
817 }
818
819 commandbuf[read] = 0;
820
821 bool ok = WStrToUtf8(commandbuf, wcslen(commandbuf), str);
822 delete[] commandbuf;
823 return ok;
824}
825
826bool WriteWinConsole(std::string_view str, bool error /*= false*/)
827{
828 std::wstring wstr;
829 wstr.reserve(str.length());
830 if (!Utf8toWStr(str, wstr))
831 return false;
832
833 HANDLE hConsole = GetStdHandle(error ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE);
834 DWORD write = 0;
835
836 return WriteConsoleW(hConsole, wstr.c_str(), wstr.size(), &write, nullptr);
837}
838#endif
839
841{
842 std::size_t nextLineIndex = str.find_first_of("\r\n");
843 if (nextLineIndex == std::string::npos)
844 return std::nullopt;
845
846 str.erase(nextLineIndex);
847 return nextLineIndex;
848}
849
850std::string Trinity::Impl::ByteArrayToHexStr(uint8 const* bytes, size_t arrayLen, bool reverse /* = false */)
851{
852 int32 init = 0;
853 int32 end = arrayLen;
854 int8 op = 1;
855
856 if (reverse)
857 {
858 init = arrayLen - 1;
859 end = -1;
860 op = -1;
861 }
862
863 std::string result;
864 result.reserve(arrayLen * 2);
865 auto inserter = std::back_inserter(result);
866 for (int32 i = init; i != end; i += op)
867 Trinity::StringFormatTo(inserter, "{:02X}", bytes[i]);
868
869 return result;
870}
871
872void Trinity::Impl::HexStrToByteArray(std::string_view str, uint8* out, size_t outlen, bool reverse /*= false*/)
873{
874 ASSERT(str.size() == (2 * outlen));
875
876 int32 init = 0;
877 int32 end = int32(str.length());
878 int8 op = 1;
879
880 if (reverse)
881 {
882 init = int32(str.length() - 2);
883 end = -2;
884 op = -1;
885 }
886
887 uint32 j = 0;
888 for (int32 i = init; i != end; i += 2 * op)
889 out[j++] = Trinity::StringTo<uint8>(str.substr(i, 2), 16).value_or(0);
890}
891
892bool StringEqualI(std::string_view a, std::string_view b)
893{
894 return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char c1, char c2) { return std::tolower(c1) == std::tolower(c2); });
895}
896
897bool StringContainsStringI(std::string_view haystack, std::string_view needle)
898{
899 return haystack.end() !=
900 std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), [](char c1, char c2) { return std::tolower(c1) == std::tolower(c2); });
901}
902
903bool StringCompareLessI(std::string_view a, std::string_view b)
904{
905 return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), [](char c1, char c2) { return std::tolower(c1) < std::tolower(c2); });
906}
907
908std::string Trinity::Impl::GetTypeName(std::type_info const& info)
909{
910 return boost::core::demangle(info.name());
911}
912
913float DegToRad(float degrees)
914{
915 return degrees * (2.f * float(M_PI) / 360.f);
916}
LocaleConstant
Definition: Common.h:48
@ LOCALE_deDE
Definition: Common.h:52
@ LOCALE_ptBR
Definition: Common.h:59
@ LOCALE_itIT
Definition: Common.h:60
@ LOCALE_esES
Definition: Common.h:55
@ LOCALE_ruRU
Definition: Common.h:57
@ LOCALE_frFR
Definition: Common.h:51
@ LOCALE_esMX
Definition: Common.h:56
@ MINUTE
Definition: Common.h:29
@ HOUR
Definition: Common.h:30
@ DAY
Definition: Common.h:31
#define M_PI
Definition: Common.h:115
uint8_t uint8
Definition: Define.h:144
int64_t int64
Definition: Define.h:137
#define TC_COMMON_API
Definition: Define.h:99
int8_t int8
Definition: Define.h:140
int32_t int32
Definition: Define.h:138
uint64_t uint64
Definition: Define.h:141
uint32_t uint32
Definition: Define.h:142
#define ABORT_MSG
Definition: Errors.h:75
#define ASSERT
Definition: Errors.h:68
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
float DegToRad(float degrees)
Definition: Util.cpp:913
bool consoleToUtf8(std::string_view conStr, std::string &utf8str)
Definition: Util.cpp:735
std::wstring GetMainPartOfName(std::wstring const &wname, uint32 declension)
Definition: Util.cpp:669
bool StringEqualI(std::string_view a, std::string_view b)
Definition: Util.cpp:892
bool WriteWinConsole(std::string_view str, bool error)
Definition: Util.cpp:826
bool WStrToUtf8(wchar_t const *wstr, size_t size, std::string &utf8str)
Definition: Util.cpp:433
bool Utf8ToUpperOnlyLatin(std::string &utf8String)
Definition: Util.cpp:795
void wstrToLower(std::wstring &str)
Definition: Util.cpp:480
bool IsIPAddress(char const *ipaddress)
Check if the string is a valid ip address representation.
Definition: Util.cpp:313
std::string TimeToTimestampStr(time_t t)
Definition: Util.cpp:290
bool StringContainsStringI(std::string_view haystack, std::string_view needle)
Definition: Util.cpp:897
time_t GetLocalHourTimestamp(time_t time, uint8 hour, bool onlyAfterTime)
Definition: Util.cpp:100
void utf8printf(FILE *out, const char *str,...)
Definition: Util.cpp:766
void strToLower(std::string &str)
Definition: Util.cpp:482
TC_COMMON_API Optional< std::size_t > RemoveCRLF(std::string &str)
Definition: Util.cpp:840
uint32 CreatePIDFile(std::string const &filename)
create PID file
Definition: Util.cpp:324
bool utf8ToConsole(std::string_view utf8str, std::string &conStr)
Definition: Util.cpp:718
tm TimeBreakdown(time_t time)
Definition: Util.cpp:93
std::wstring wstrCaseAccentInsensitiveParse(std::wstring_view wstr, LocaleConstant locale)
Definition: Util.cpp:484
std::string TimeToHumanReadable(time_t t)
Definition: Util.cpp:303
bool StringCompareLessI(std::string_view a, std::string_view b)
Definition: Util.cpp:903
bool Utf8FitTo(std::string_view str, std::wstring_view search)
Definition: Util.cpp:750
std::string secsToTimeString(uint64 timeInSecs, TimeFormat timeFormat, bool hoursOnly)
Definition: Util.cpp:115
uint32 GetPID()
Definition: Util.cpp:338
bool Utf8toWStr(char const *utf8str, size_t csize, wchar_t *wstr, size_t &wsize)
Definition: Util.cpp:383
Optional< int64 > MoneyStringToMoney(std::string const &moneyString)
Definition: Util.cpp:216
bool ReadWinConsole(std::string &str, size_t size)
Definition: Util.cpp:807
size_t utf8length(std::string &utf8str)
Definition: Util.cpp:349
void utf8truncate(std::string &utf8str, size_t len)
Definition: Util.cpp:362
uint32 TimeStringToSecs(std::string const &timestring)
Definition: Util.cpp:258
void wstrToUpper(std::wstring &str)
Definition: Util.cpp:479
void strToUpper(std::string &str)
Definition: Util.cpp:481
void vutf8printf(FILE *out, const char *str, va_list *ap)
Definition: Util.cpp:774
struct WcharToUpperOnlyLatin wcharToUpperOnlyLatin
TimeFormat
Definition: Util.h:35
struct WcharToLower wcharToLower
struct CharToUpper charToUpper
bool isCyrillicCharacter(wchar_t wchar)
Definition: Util.h:154
struct CharToLower charToLower
struct WcharToUpper wcharToUpper
TC_COMMON_API void HexStrToByteArray(std::string_view str, uint8 *out, size_t outlen, bool reverse=false)
Definition: Util.cpp:872
TC_COMMON_API std::string ByteArrayToHexStr(uint8 const *bytes, size_t length, bool reverse=false)
Definition: Util.cpp:850
TC_COMMON_API std::string GetTypeName(std::type_info const &)
Definition: Util.cpp:908
TC_COMMON_API void VerifyOsVersion()
Definition: Util.cpp:34
TC_COMMON_API std::vector< std::string_view > Tokenize(std::string_view str, char sep, bool keepEmpty)
Definition: Util.cpp:56
OutputIt StringFormatTo(OutputIt out, FormatString< Args... > fmt, Args &&... args)
Definition: StringFormat.h:51
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
Definition: StringFormat.h:38
constexpr std::size_t size()
Definition: UpdateField.h:805