Legends-of-Azeroth-Pandaria-5.4.8

Форк
0
655 строк · 17.4 Кб
1
/*
2
* This file is part of the Pandaria 5.4.8 Project. See THANKS 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

19
#include "Common.h"
20
#include "Errors.h" // for ASSERT
21
#include "IpAddress.h"
22
#include "Util.h"
23
#include "utf8.h"
24
#include <memory>
25
#include <random>
26
#include <cstring>
27
#include <sstream>
28
#include <cstdarg>
29

30
std::vector<std::string_view> Trinity::Tokenize(std::string_view str, char sep, bool keepEmpty)
31
{
32
    std::vector<std::string_view> tokens;
33

34
    size_t start = 0;
35
    for (size_t end = str.find(sep); end != std::string_view::npos; end = str.find(sep, start))
36
    {
37
        if (keepEmpty || (start < end))
38
            tokens.push_back(str.substr(start, end - start));
39
        start = end+1;
40
    }
41

42
    if (keepEmpty || (start < str.length()))
43
        tokens.push_back(str.substr(start));
44

45
    return tokens;
46
}
47

48
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
49
struct tm* localtime_r(time_t const* time, struct tm *result)
50
{
51
    localtime_s(result, time);
52
    return result;
53
}
54
#endif
55

56
Tokenizer::Tokenizer(const std::string &src, const char sep, uint32 vectorReserve)
57
{
58
    m_str = new char[src.length() + 1];
59
    memcpy(m_str, src.c_str(), src.length() + 1);
60

61
    if (vectorReserve)
62
        m_storage.reserve(vectorReserve);
63

64
    char* posold = m_str;
65
    char* posnew = m_str;
66

67
    for (;;)
68
    {
69
        if (*posnew == sep)
70
        {
71
            m_storage.push_back(posold);
72
            posold = posnew + 1;
73

74
            *posnew = '\0';
75
        }
76
        else if (*posnew == '\0')
77
        {
78
            // Hack like, but the old code accepted these kind of broken strings,
79
            // so changing it would break other things
80
            if (posold != posnew)
81
                m_storage.push_back(posold);
82

83
            break;
84
        }
85

86
        ++posnew;
87
    }
88
}
89

90
void stripLineInvisibleChars(std::string &str)
91
{
92
    static std::string const invChars = " \t\7\n";
93

94
    size_t wpos = 0;
95

96
    bool space = false;
97
    for (size_t pos = 0; pos < str.size(); ++pos)
98
    {
99
        if (invChars.find(str[pos])!=std::string::npos)
100
        {
101
            if (!space)
102
            {
103
                str[wpos++] = ' ';
104
                space = true;
105
            }
106
        }
107
        else
108
        {
109
            if (wpos!=pos)
110
                str[wpos++] = str[pos];
111
            else
112
                ++wpos;
113
            space = false;
114
        }
115
    }
116

117
    if (wpos < str.size())
118
        str.erase(wpos, str.size());
119
    if (str.find("|TInterface")!=std::string::npos)
120
        str.clear();
121

122
}
123

124
std::string secsToTimeString(uint64 timeInSecs, bool shortText, bool hoursOnly)
125
{
126
    uint64 secs    = timeInSecs % MINUTE;
127
    uint64 minutes = timeInSecs % HOUR / MINUTE;
128
    uint64 hours   = timeInSecs % DAY  / HOUR;
129
    uint64 days    = timeInSecs / DAY;
130

131
    std::ostringstream ss;
132
    if (days)
133
        ss << days << (shortText ? "d" : " Day(s) ");
134
    if (hours || hoursOnly)
135
        ss << hours << (shortText ? "h" : " Hour(s) ");
136
    if (!hoursOnly)
137
    {
138
        if (minutes)
139
            ss << minutes << (shortText ? "m" : " Minute(s) ");
140
        if (secs || (!days && !hours && !minutes) )
141
            ss << secs << (shortText ? "s" : " Second(s).");
142
    }
143

144
    return ss.str();
145
}
146

147
int64 MoneyStringToMoney(const std::string& moneyString)
148
{
149
    int64 money = 0;
150

151
    if (!(std::count(moneyString.begin(), moneyString.end(), 'g') == 1 ||
152
        std::count(moneyString.begin(), moneyString.end(), 's') == 1 ||
153
        std::count(moneyString.begin(), moneyString.end(), 'c') == 1))
154
        return 0; // Bad format
155

156
    Tokenizer tokens(moneyString, ' ');
157
    for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr)
158
    {
159
        std::string tokenString(*itr);
160
        size_t gCount = std::count(tokenString.begin(), tokenString.end(), 'g');
161
        size_t sCount = std::count(tokenString.begin(), tokenString.end(), 's');
162
        size_t cCount = std::count(tokenString.begin(), tokenString.end(), 'c');
163
        if (gCount + sCount + cCount != 1)
164
            return 0;
165

166
        uint64 amount = atol(*itr);
167
        if (gCount == 1)
168
            money += amount * 100 * 100;
169
        else if (sCount == 1)
170
            money += amount * 100;
171
        else if (cCount == 1)
172
            money += amount;
173
    }
174

175
    return money;
176
}
177

178
uint32 TimeStringToSecs(const std::string& timestring)
179
{
180
    uint32 secs       = 0;
181
    uint32 buffer     = 0;
182
    uint32 multiplier = 0;
183

184
    for (std::string::const_iterator itr = timestring.begin(); itr != timestring.end(); ++itr)
185
    {
186
        if (isdigit(*itr))
187
        {
188
            buffer*=10;
189
            buffer+= (*itr)-'0';
190
        }
191
        else
192
        {
193
            switch (*itr)
194
            {
195
                case 'd': multiplier = DAY;     break;
196
                case 'h': multiplier = HOUR;    break;
197
                case 'm': multiplier = MINUTE;  break;
198
                case 's': multiplier = 1;       break;
199
                default : return 0;                         //bad format
200
            }
201
            buffer*=multiplier;
202
            secs+=buffer;
203
            buffer=0;
204
        }
205
    }
206

207
    return secs;
208
}
209

210
std::string TimeToTimestampStr(time_t t)
211
{
212
    tm aTm;
213
    localtime_r(&t, &aTm);
214
    //       YYYY   year
215
    //       MM     month (2 digits 01-12)
216
    //       DD     day (2 digits 01-31)
217
    //       HH     hour (2 digits 00-23)
218
    //       MM     minutes (2 digits 00-59)
219
    //       SS     seconds (2 digits 00-59)
220
    char buf[20];
221
    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);
222
    return std::string(buf);
223
}
224

225
/// Check if the string is a valid ip address representation
226
bool IsIPAddress(char const* ipaddress)
227
{
228
    if (!ipaddress)
229
        return false;
230

231
    boost::system::error_code error;
232
    Trinity::Net::make_address(ipaddress, error);
233
    return !error;
234
}
235

236
/// create PID file
237
uint32 CreatePIDFile(const std::string& filename)
238
{
239
    FILE* pid_file = fopen (filename.c_str(), "w" );
240
    if (pid_file == NULL)
241
        return 0;
242

243
#ifdef _WIN32
244
    DWORD pid = GetCurrentProcessId();
245
#else
246
    pid_t pid = getpid();
247
#endif
248

249
    fprintf(pid_file, "%u", pid );
250
    fclose(pid_file);
251

252
    return (uint32)pid;
253
}
254

255
size_t utf8length(std::string& utf8str)
256
{
257
    try
258
    {
259
        return utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size());
260
    }
261
    catch(std::exception)
262
    {
263
        utf8str = "";
264
        return 0;
265
    }
266
}
267

268
void utf8truncate(std::string& utf8str, size_t len)
269
{
270
    try
271
    {
272
        size_t wlen = utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size());
273
        if (wlen <= len)
274
            return;
275

276
        std::wstring wstr;
277
        wstr.resize(wlen * 2);                              // allocate for most long case
278
        utf8::utf8to16(utf8str.c_str(), utf8str.c_str()+utf8str.size(), &wstr[0]);
279
        wstr.resize(len);                                   // TODO: Possible error here - can split surrogate pair in half
280
        char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str()+wstr.size(), &utf8str[0]);
281
        utf8str.resize(oend-(&utf8str[0]));                 // remove unused tail
282
    }
283
    catch(std::exception)
284
    {
285
        utf8str = "";
286
    }
287
}
288

289
bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize)
290
{
291
    try
292
    {
293
        size_t len = utf8::distance(utf8str, utf8str + csize);
294
        if (len > wsize)
295
        {
296
            if (wsize > 0)
297
                wstr[0] = L'\0';
298
            wsize = 0;
299
            return false;
300
        }
301

302
        wsize = len;
303
        utf8::utf8to16(utf8str, utf8str + csize, wstr);
304
        wstr[len] = L'\0';
305
    }
306
    catch (std::exception)
307
    {
308
        if (wsize > 0)
309
            wstr[0] = L'\0';
310
        wsize = 0;
311
        return false;
312
    }
313

314
    return true;
315
}
316

317
bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr)
318
{
319
    wstr.clear();
320
    try
321
    {
322
        utf8::utf8to16(utf8str.c_str(), utf8str.c_str()+utf8str.size(), std::back_inserter(wstr));
323
    }
324
    catch(std::exception const&)
325
    {
326
        wstr.clear();
327
        return false;
328
    }
329

330
    return true;
331
}
332

333
bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str)
334
{
335
    try
336
    {
337
        std::string utf8str2;
338
        utf8str2.resize(size*4);                            // allocate for most long case
339

340
        if (size)
341
        {
342
            char* oend = utf8::utf16to8(wstr, wstr+size, &utf8str2[0]);
343
            utf8str2.resize(oend-(&utf8str2[0]));               // remove unused tail
344
        }
345
        utf8str = utf8str2;
346
    }
347
    catch(std::exception)
348
    {
349
        utf8str = "";
350
        return false;
351
    }
352

353
    return true;
354
}
355

356
bool WStrToUtf8(std::wstring wstr, std::string& utf8str)
357
{
358
    try
359
    {
360
        std::string utf8str2;
361
        utf8str2.resize(wstr.size()*4);                     // allocate for most long case
362

363
        if (wstr.size())
364
        {
365
            char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str()+wstr.size(), &utf8str2[0]);
366
            utf8str2.resize(oend-(&utf8str2[0]));                // remove unused tail
367
        }
368
        utf8str = utf8str2;
369
    }
370
    catch(std::exception)
371
    {
372
        utf8str = "";
373
        return false;
374
    }
375

376
    return true;
377
}
378

379
bool WStrToUtf8(std::wstring_view wstr, std::string& utf8str)
380
{
381
    try
382
    {
383
        std::string utf8str2;
384
        utf8str2.resize(wstr.size()*4);                     // allocate for most long case
385

386
        if (!wstr.empty())
387
        {
388
            char* oend = utf8::utf16to8(wstr.begin(), wstr.end(), &utf8str2[0]);
389
            utf8str2.resize(oend-(&utf8str2[0]));                // remove unused tail
390
        }
391
        utf8str = utf8str2;
392
    }
393
    catch(std::exception const&)
394
    {
395
        utf8str.clear();
396
        return false;
397
    }
398

399
    return true;
400
}
401

402
#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
403
bool ReadWinConsole(std::string& str, size_t size /*= 256*/)
404
{
405
    wchar_t* commandbuf = new wchar_t[size + 1];
406
    HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
407
    DWORD read = 0;
408

409
    if (!ReadConsoleW(hConsole, commandbuf, size, &read, nullptr) || read == 0)
410
    {
411
        delete[] commandbuf;
412
        return false;
413
    }
414

415
    commandbuf[read] = 0;
416

417
    bool ok = WStrToUtf8(commandbuf, wcslen(commandbuf), str);
418
    delete[] commandbuf;
419
    return ok;
420
}
421

422
bool WriteWinConsole(std::string_view str, bool error /*= false*/)
423
{
424
    std::wstring wstr;
425
    if (!Utf8toWStr(str, wstr))
426
        return false;
427

428
    HANDLE hConsole = GetStdHandle(error ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE);
429
    DWORD write = 0;
430

431
    return WriteConsoleW(hConsole, wstr.c_str(), wstr.size(), &write, nullptr);
432
}
433
#endif
434

435
typedef wchar_t const* const* wstrlist;
436

437
std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension)
438
{
439
    // supported only Cyrillic cases
440
    if (wname.empty() || !isCyrillicCharacter(wname[0]) || declension > 5)
441
        return wname;
442

443
    // Important: end length must be <= MAX_INTERNAL_PLAYER_NAME-MAX_PLAYER_NAME (3 currently)
444
    static std::wstring const a_End = { wchar_t(0x0430), wchar_t(0x0000) };
445
    static std::wstring const o_End = { wchar_t(0x043E), wchar_t(0x0000) };
446
    static std::wstring const ya_End = { wchar_t(0x044F), wchar_t(0x0000) };
447
    static std::wstring const ie_End = { wchar_t(0x0435), wchar_t(0x0000) };
448
    static std::wstring const i_End = { wchar_t(0x0438), wchar_t(0x0000) };
449
    static std::wstring const yeru_End = { wchar_t(0x044B), wchar_t(0x0000) };
450
    static std::wstring const u_End = { wchar_t(0x0443), wchar_t(0x0000) };
451
    static std::wstring const yu_End = { wchar_t(0x044E), wchar_t(0x0000) };
452
    static std::wstring const oj_End = { wchar_t(0x043E), wchar_t(0x0439), wchar_t(0x0000) };
453
    static std::wstring const ie_j_End = { wchar_t(0x0435), wchar_t(0x0439), wchar_t(0x0000) };
454
    static std::wstring const io_j_End = { wchar_t(0x0451), wchar_t(0x0439), wchar_t(0x0000) };
455
    static std::wstring const o_m_End = { wchar_t(0x043E), wchar_t(0x043C), wchar_t(0x0000) };
456
    static std::wstring const io_m_End = { wchar_t(0x0451), wchar_t(0x043C), wchar_t(0x0000) };
457
    static std::wstring const ie_m_End = { wchar_t(0x0435), wchar_t(0x043C), wchar_t(0x0000) };
458
    static std::wstring const soft_End = { wchar_t(0x044C), wchar_t(0x0000) };
459
    static std::wstring const j_End = { wchar_t(0x0439), wchar_t(0x0000) };
460

461
    static std::array<std::array<std::wstring const*, 7>, 6> const dropEnds = { {
462
        { &a_End,  &o_End,    &ya_End,   &ie_End,  &soft_End, &j_End,    nullptr },
463
        { &a_End,  &ya_End,   &yeru_End, &i_End,   nullptr,   nullptr,   nullptr },
464
        { &ie_End, &u_End,    &yu_End,   &i_End,   nullptr,   nullptr,   nullptr },
465
        { &u_End,  &yu_End,   &o_End,    &ie_End,  &soft_End, &ya_End,   &a_End  },
466
        { &oj_End, &io_j_End, &ie_j_End, &o_m_End, &io_m_End, &ie_m_End, &yu_End },
467
        { &ie_End, &i_End,    nullptr,   nullptr,  nullptr,   nullptr,   nullptr }
468
    } };
469

470
    std::size_t const thisLen = wname.length();
471
    std::array<std::wstring const*, 7> const& endings = dropEnds[declension];
472
    for (auto itr = endings.begin(), end = endings.end(); (itr != end) && *itr; ++itr)
473
    {
474
        std::wstring const& ending = **itr;
475
        std::size_t const endLen = ending.length();
476
        if (!(endLen <= thisLen))
477
            continue;
478

479
        if (wname.substr(thisLen - endLen, thisLen) == ending)
480
            return wname.substr(0, thisLen - endLen);
481
    }
482

483
    return wname;
484
}
485

486

487
bool utf8ToConsole(const std::string& utf8str, std::string& conStr)
488
{
489
#if PLATFORM == PLATFORM_WINDOWS
490
    std::wstring wstr;
491
    if (!Utf8toWStr(utf8str, wstr))
492
        return false;
493

494
    conStr.resize(wstr.size());
495
    CharToOemBuffW(&wstr[0], &conStr[0], wstr.size());
496
#else
497
    // not implemented yet
498
    conStr = utf8str;
499
#endif
500

501
    return true;
502
}
503

504
bool Utf8toWStr(std::string_view utf8str, std::wstring& wstr)
505
{
506
    wstr.clear();
507
    try
508
    {
509
        utf8::utf8to16(utf8str.begin(), utf8str.end(), std::back_inserter(wstr));
510
    }
511
    catch(std::exception const&)
512
    {
513
        wstr.clear();
514
        return false;
515
    }
516

517
    return true;
518
}
519

520
bool consoleToUtf8(const std::string& conStr, std::string& utf8str)
521
{
522
#if PLATFORM == PLATFORM_WINDOWS
523
    std::wstring wstr;
524
    wstr.resize(conStr.size());
525
    OemToCharBuffW(&conStr[0], &wstr[0], conStr.size());
526

527
    return WStrToUtf8(wstr, utf8str);
528
#else
529
    // not implemented yet
530
    utf8str = conStr;
531
    return true;
532
#endif
533
}
534

535
bool Utf8FitTo(const std::string& str, std::wstring search)
536
{
537
    std::wstring temp;
538

539
    if (!Utf8toWStr(str, temp))
540
        return false;
541

542
    // converting to lower case
543
    wstrToLower( temp );
544

545
    if (temp.find(search) == std::wstring::npos)
546
        return false;
547

548
    return true;
549
}
550

551
void utf8printf(FILE* out, const char *str, ...)
552
{
553
    va_list ap;
554
    va_start(ap, str);
555
    vutf8printf(out, str, &ap);
556
    va_end(ap);
557
}
558

559
void vutf8printf(FILE* out, const char *str, va_list* ap)
560
{
561
#if PLATFORM == PLATFORM_WINDOWS
562
    char temp_buf[32*1024];
563
    wchar_t wtemp_buf[32*1024];
564

565
    size_t temp_len = vsnprintf(temp_buf, 32*1024, str, *ap);
566

567
    size_t wtemp_len = 32*1024-1;
568
    Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len);
569

570
    CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], wtemp_len+1);
571
    fprintf(out, "%s", temp_buf);
572
#else
573
    vfprintf(out, str, *ap);
574
#endif
575
}
576

577
bool Utf8ToUpperOnlyLatin(std::string& utf8String)
578
{
579
    std::wstring wstr;
580
    if (!Utf8toWStr(utf8String, wstr))
581
        return false;
582

583
    std::transform(wstr.begin(), wstr.end(), wstr.begin(), wcharToUpperOnlyLatin);
584

585
    return WStrToUtf8(wstr, utf8String);
586
}
587

588
TC_COMMON_API Optional<std::size_t> RemoveCRLF(std::string & str)
589
{
590
    std::size_t nextLineIndex = str.find_first_of("\r\n");
591
    if (nextLineIndex == std::string::npos)
592
        return std::nullopt;
593

594
    str.erase(nextLineIndex);
595
    return nextLineIndex;
596
}
597

598
std::string Trinity::Impl::ByteArrayToHexStr(uint8 const* bytes, size_t arrayLen, bool reverse /* = false */)
599
{
600
    int32 init = 0;
601
    int32 end = arrayLen;
602
    int8 op = 1;
603

604
    if (reverse)
605
    {
606
        init = arrayLen - 1;
607
        end = -1;
608
        op = -1;
609
    }
610

611
    std::ostringstream ss;
612
    for (int32 i = init; i != end; i += op)
613
    {
614
        char buffer[4];
615
        sprintf(buffer, "%02X", bytes[i]);
616
        ss << buffer;
617
    }
618

619
    return ss.str();
620
}
621

622
void Trinity::Impl::HexStrToByteArray(std::string_view str, uint8* out, size_t outlen, bool reverse /*= false*/)
623
{
624
    ASSERT(str.size() == (2 * outlen));
625

626
    int32 init = 0;
627
    int32 end = int32(str.length());
628
    int8 op = 1;
629

630
    if (reverse)
631
    {
632
        init = int32(str.length() - 2);
633
        end = -2;
634
        op = -1;
635
    }
636

637
    uint32 j = 0;
638
    for (int32 i = init; i != end; i += 2 * op)
639
    {
640
        char buffer[3] = { str[i], str[i + 1], '\0' };
641
        out[j++] = uint8(strtoul(buffer, nullptr, 16));
642
    }
643
}
644

645
bool StringEqualI(std::string_view a, std::string_view b)
646
{
647
    return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char c1, char c2) { return std::tolower(c1) == std::tolower(c2); });
648
}
649

650
bool StringToBool(std::string const& str)
651
{
652
    std::string lowerStr = str;
653
    std::transform(str.begin(), str.end(), lowerStr.begin(), ::tolower);
654
    return lowerStr == "1" || lowerStr == "true" || lowerStr == "yes";
655
}
656

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.