Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 andreas 1
/*
99 andreas 2
 * Copyright (C) 2020 to 2022 by Andreas Theofilu <andreas@theosys.at>
4 andreas 3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software Foundation,
16
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
17
 */
18
 
19
#include <include/core/SkBitmap.h>
20
#include <include/core/SkData.h>
21
#include <include/core/SkImage.h>
22
#include <include/core/SkImageGenerator.h>
23
#include <include/core/SkStream.h>
57 andreas 24
#include <include/core/SkFont.h>
4 andreas 25
#include <include/core/SkTypeface.h>
26
 
11 andreas 27
#include <iconv.h>
71 andreas 28
#include <libgen.h>
11 andreas 29
 
125 andreas 30
#include <sys/types.h>
31
#include <sys/stat.h>
32
 
4 andreas 33
#include "tresources.h"
34
#include "terror.h"
35
#include "tconfig.h"
36
 
37
using std::string;
38
using std::endl;
11 andreas 39
using std::vector;
4 andreas 40
 
11 andreas 41
typedef struct
42
{
43
    unsigned char ch;
70 andreas 44
    unsigned int byte;
11 andreas 45
}CHTABLE;
46
 
47
static CHTABLE __cht[] = {
70 andreas 48
    {0x80,	0xE282AC},
49
    {0x81,	0x0081},    // not used
50
    {0x82,	0xE2809A},
51
    {0x83,	0x0192},    // not used
52
    {0x84,	0xE2809E},
53
    {0x85,	0xE280A6},
54
    {0x86,	0xE280A0},
55
    {0x87,	0xE280A1},
56
    {0x88,	0x02C6},    // not used
57
    {0x89,	0xE280B0},
58
    {0x8A,	0xC5A0},
59
    {0x8B,	0xE280B9},
60
    {0x8C,	0xC59A},
61
    {0x8D,	0xC5A4},
62
    {0x8E,	0xC5BD},
63
    {0x8F,	0xC5B9},
64
    {0x90,	0x0090},    // not used
65
    {0x91,	0xE28098},
66
    {0x92,	0xE28099},
67
    {0x93,	0xE2809C},
68
    {0x94,	0xE2809D},
69
    {0x95,	0xE280A2},
70
    {0x96,	0xE28093},
71
    {0x97,	0xE28094},
72
    {0x98,	0x02DC},    // not used
73
    {0x99,	0xE284A2},
74
    {0x9A,	0xC5A1},
75
    {0x9B,	0xE280BA},
76
    {0x9C,	0xC59B},
77
    {0x9D,	0xC5A5},
78
    {0x9E,	0xC5BE},
79
    {0x9F,	0xC5BA},
80
    {0xA0,	0xC2A0},
81
    {0xA1,	0xCB87},
82
    {0xA2,	0xCB98},
83
    {0xA3,	0xC581},
84
    {0xA4,	0xC2A0},
85
    {0xA5,	0xC484},
86
    {0xA6,	0xC2A6},
87
    {0xA7,	0xC2A7},
88
    {0xA8,	0xC2A8},
89
    {0xA9,	0xC2A9},
90
    {0xAA,	0xC59E},
91
    {0xAB,	0xC2AB},
92
    {0xAC,	0xC2AC},
93
    {0xAD,	0xC2AD},
94
    {0xAE,	0xC2AE},
95
    {0xAF,	0xC5BB},
96
    {0xB0,	0xC2B0},
97
    {0xB1,	0xC2B1},
98
    {0xB2,	0xCB9B},
99
    {0xB3,	0xC582},
100
    {0xB4,	0xC2B4},
101
    {0xB5,	0xC2B5},
102
    {0xB6,	0xC2B6},
103
    {0xB7,	0xC2B7},
104
    {0xB8,	0xC2B8},
105
    {0xB9,	0xC485},
106
    {0xBA,	0xC59F},
107
    {0xBB,	0xC2BB},
108
    {0xBC,	0xC4BD},
109
    {0xBD,	0xCB9D},
110
    {0xBE,	0xC4BE},
111
    {0xBF,	0xC5BC},
112
    {0xC0,	0xC594},
113
    {0xC1,	0xC381},
114
    {0xC2,	0xC382},
115
    {0xC3,	0xC482},
116
    {0xC4,	0xC384},
117
    {0xC5,	0xC4B9},
118
    {0xC6,	0xC486},
119
    {0xC7,	0xC387},
120
    {0xC8,	0xC48C},
121
    {0xC9,	0xC389},
122
    {0xCA,	0xC489},
123
    {0xCB,	0xC38b},
124
    {0xCC,	0xC49A},
125
    {0xCD,	0xC38D},
126
    {0xCE,	0xC38E},
127
    {0xCF,	0xC48E},
128
    {0xD0,	0xC490},
129
    {0xD1,	0xC583},
130
    {0xD2,	0xC587},
131
    {0xD3,	0xC398},
132
    {0xD4,	0xC394},
133
    {0xD5,	0xC590},
134
    {0xD6,	0xC396},
135
    {0xD7,	0xC397},
136
    {0xD8,	0xC598},
137
    {0xD9,	0xC5AE},
138
    {0xDA,	0xC39A},
139
    {0xDB,	0xC5B0},
140
    {0xDC,	0xC39C},
141
    {0xDD,	0xC39D},
142
    {0xDE,	0xC5A2},
143
    {0xDF,	0xC39F},
144
    {0xE0,	0xC595},
145
    {0xE1,	0xC3A1},
146
    {0xE2,	0xC3A2},
147
    {0xE3,	0xC483},
148
    {0xE4,	0xC3A4},
149
    {0xE5,	0xC4BA},
150
    {0xE6,	0xC487},
151
    {0xE7,	0xC3A7},
152
    {0xE8,	0xC48D},
153
    {0xE9,	0xC3A9},
154
    {0xEA,	0xC499},
155
    {0xEB,	0xC3AB},
156
    {0xEC,	0xC49B},
157
    {0xED,	0xC3AD},
158
    {0xEE,	0xC3AE},
159
    {0xEF,	0xC48F},
160
    {0xF0,	0xC491},
161
    {0xF1,	0xC584},
162
    {0xF2,	0xC588},
163
    {0xF3,	0xC3B3},
164
    {0xF4,	0xC3B4},
165
    {0xF5,	0xC591},
166
    {0xF6,	0xC3B6},
167
    {0xF7,	0xC3B7},
168
    {0xF8,	0xC599},
169
    {0xF9,	0xC5AF},
170
    {0xFA,	0xC3BA},
171
    {0xFB,	0xC5B1},
172
    {0xFC,	0xC3BC},
173
    {0xFD,	0xC3BD},
174
    {0xFE,	0xC5A3},
175
    {0xFF,	0xCB99}
11 andreas 176
};
177
 
156 andreas 178
SkString GetResourcePath(const char* resource, _RESOURCE_TYPE rs)
4 andreas 179
{
163 andreas 180
    if (!resource)
181
        return SkString();
182
 
183
    if (*resource == '/')       // absolute path?
184
    {                           // yes, then take it as it is
185
        return SkString(resource);
186
    }
187
 
156 andreas 188
    string pth;
67 andreas 189
 
156 andreas 190
    switch(rs)
191
    {
192
        case RESTYPE_BORDER:    pth = "/borders/"; break;
193
        case RESTYPE_CURSOR:    pth = "/cursors/"; break;
194
        case RESTYPE_FONT:      pth = "/fonts/"; break;
195
        case RESTYPE_UNKNOWN:
196
        case RESTYPE_IMAGE:     pth = "/images/"; break;
161 andreas 197
        case RESTYPE_SLIDER:    pth = "/sliders/"; break;
198
        case RESTYPE_SYSBORDER: pth = "/__system/graphics/borders/"; break;
199
        case RESTYPE_SYSCURSOR: pth = "/__system/graphics/cursors/"; break;
200
        case RESTYPE_SYSFONT:   pth = "/__system/graphics/fonts/"; break;
201
        case RESTYPE_SYSIMAGE:  pth = "/__system/graphics/images/"; break;
202
        case RESTYPE_SYSSLIDER: pth = "/__system/graphics/sliders/"; break;
156 andreas 203
    }
204
 
205
    string path = TConfig::getProjectPath() + pth + resource;
206
 
4 andreas 207
    return SkString(path);
208
}
209
 
210
bool DecodeDataToBitmap(sk_sp<SkData> data, SkBitmap* dst)
211
{
212
    std::unique_ptr<SkImageGenerator> gen(SkImageGenerator::MakeFromEncoded(std::move(data)));
213
    return gen && dst->tryAllocPixels(gen->getInfo()) &&
23 andreas 214
#ifdef __ANDROID__
215
    gen->getPixels(gen->getInfo().makeColorType(kBGRA_8888_SkColorType).makeAlphaType(kPremul_SkAlphaType), dst->getPixels(), dst->rowBytes());
216
#else
4 andreas 217
    gen->getPixels(gen->getInfo().makeColorSpace(nullptr), dst->getPixels(), dst->rowBytes());
23 andreas 218
#endif
4 andreas 219
}
220
 
156 andreas 221
std::unique_ptr<SkStreamAsset> GetResourceAsStream(const char* resource, _RESOURCE_TYPE rs)
4 andreas 222
{
156 andreas 223
    sk_sp<SkData> data = GetResourceAsData(resource, rs);
4 andreas 224
    return data ? std::unique_ptr<SkStreamAsset>(new SkMemoryStream(std::move(data)))
225
    : nullptr;
226
}
227
 
156 andreas 228
sk_sp<SkData> GetResourceAsData(const char* resource, _RESOURCE_TYPE rs)
4 andreas 229
{
163 andreas 230
    SkString str = GetResourcePath(resource, rs);
231
    sk_sp<SkData> data = SkData::MakeFromFileName(str.c_str());
232
 
233
    if (data)
4 andreas 234
        return data;
235
 
163 andreas 236
    MSG_ERROR("GetResourceAsData: Resource \"" << str.c_str() << "\" not found.");
4 andreas 237
    TError::setError();
238
#ifdef SK_TOOLS_REQUIRE_RESOURCES
6 andreas 239
    SK_ABORT("GetResourceAsData: missing resource");
4 andreas 240
#endif
241
    return nullptr;
242
}
243
 
156 andreas 244
sk_sp<SkTypeface> MakeResourceAsTypeface(const char* resource, int ttcIndex, _RESOURCE_TYPE rs)
4 andreas 245
{
156 andreas 246
    return SkTypeface::MakeFromStream(GetResourceAsStream(resource, rs), ttcIndex);
4 andreas 247
}
6 andreas 248
 
249
/*
250
 * Read the image from a file and save it into a data buffer. This is the base
251
 * to convert the image.
252
 */
253
sk_sp<SkData> readImage(const string& fname)
254
{
255
    sk_sp<SkData> data = GetResourceAsData(fname.c_str());
256
 
257
    if (!data)
258
    {
259
        MSG_ERROR("readImage: Error loading the image " << fname);
260
        TError::setError();
261
    }
262
 
263
    return data;
264
}
11 andreas 265
 
266
vector<string> StrSplit(const string& str, const string& seps, const bool trimEmpty)
267
{
268
    size_t pos = 0, mark = 0;
269
    vector<string> parts;
270
    string::const_iterator it, sepIt;
271
 
96 andreas 272
    if (str.empty())
273
        return parts;
274
 
11 andreas 275
    for (it = str.begin(); it != str.end(); ++it)
276
    {
277
        for (sepIt = seps.begin(); sepIt != seps.end(); ++sepIt)
278
        {
21 andreas 279
            if (pos > 0 && *it == *sepIt)
11 andreas 280
            {
281
                size_t len = pos - mark;
21 andreas 282
 
96 andreas 283
                if (len > 0 && *sepIt != '\n')
21 andreas 284
                    parts.push_back(str.substr(mark, len));
96 andreas 285
                else if (len > 0)
286
                    parts.push_back(str.substr(mark, len) + "\n");
164 andreas 287
                else if (*sepIt == '\n')
288
                    parts.push_back("\n");
21 andreas 289
                else
290
                    parts.push_back(string());
291
 
11 andreas 292
                mark = pos + 1;
293
                break;
294
            }
21 andreas 295
            else if (*it == *sepIt)
96 andreas 296
            {
297
                if (*sepIt == '\n')
298
                    parts.push_back("\n");
299
 
21 andreas 300
                mark = pos + 1;
96 andreas 301
            }
11 andreas 302
        }
303
 
304
        pos++;
305
    }
306
 
307
    parts.push_back(str.substr(mark));
308
 
309
    if (trimEmpty)
310
    {
311
        vector<string> nparts;
312
 
96 andreas 313
        for (auto iter = parts.begin(); iter != parts.end(); ++iter)
11 andreas 314
        {
96 andreas 315
            if (iter->empty())
11 andreas 316
                continue;
317
 
96 andreas 318
            nparts.push_back(*iter);
11 andreas 319
        }
320
 
321
        return nparts;
322
    }
323
 
324
    return parts;
325
}
326
 
327
string latin1ToUTF8(const string& str)
328
{
329
    DECL_TRACER("NameFormat::latin1ToUTF8(const string& str)");
330
    string out;
331
 
332
    for (size_t i = 0; i < str.length(); i++)
333
    {
334
        uint8_t ch = str.at(i);
335
 
336
        if (ch < 0x80)
337
        {
338
            out.push_back(ch);
339
        }
340
        else
341
        {
342
            out.push_back(0xc0 | ch >> 6);
343
            out.push_back(0x80 | (ch & 0x3f));
344
        }
345
    }
346
 
347
    return out;
348
}
349
 
350
string cp1250ToUTF8(const string& str)
351
{
352
    DECL_TRACER("cp1250ToUTF8(const string& str)");
353
 
354
    string out;
355
 
356
    for (size_t j = 0; j < str.length(); j++)
357
    {
358
        int i = -1;
359
        unsigned char ch = str.at(j);
70 andreas 360
        unsigned int utf = 0x80000000;
11 andreas 361
 
70 andreas 362
        if (ch >= 0x80)
11 andreas 363
        {
364
            do
365
            {
366
                i++;
367
 
368
                if (__cht[i].ch == ch)
369
                {
370
                    utf = __cht[i].byte;
371
                    break;
372
                }
373
            }
374
            while (__cht[i].ch != 0xff);
375
 
70 andreas 376
            if (utf == 0x80000000)
11 andreas 377
                utf = ch;
378
        }
379
        else
380
            utf = ch;
381
 
70 andreas 382
        if (utf > 0x00ffff)
11 andreas 383
        {
70 andreas 384
            out.push_back((utf >> 16) & 0x0000ff);
385
            out.push_back((utf >> 8) & 0x0000ff);
386
            out.push_back(utf & 0x0000ff);
11 andreas 387
        }
70 andreas 388
        else if (utf > 0x0000ff)
389
        {
390
            out.push_back((utf >> 8) & 0x0000ff);
391
            out.push_back(utf & 0x0000ff);
392
        }
11 andreas 393
        else if (ch > 0x7f)
394
        {
395
            out.push_back(0xc0 | ch >> 6);
396
            out.push_back(0x80 | (ch & 0x3f));
397
        }
398
        else
399
            out.push_back(ch);
400
    }
401
 
402
    return out;
403
}
404
 
405
string UTF8ToCp1250(const string& str)
406
{
407
    DECL_TRACER("UTF8ToCp1250(const string& str)");
70 andreas 408
#ifdef __ANDROID__
409
    string out;
410
    string::const_iterator iter;
411
    bool three = false;
11 andreas 412
 
70 andreas 413
    for (iter = str.begin(); iter != str.end(); ++iter)
414
    {
415
        unsigned int uch;
416
 
417
        if ((*iter & 0xc0) == 0xc0)     // If UTF8 then we need the next char also
418
        {
419
            uch = 0;
420
 
421
            if ((*iter & 0xe0) == 0xe0) // UTF8 consists of 3 bytes?
422
            {
423
                uch = (*iter << 16) & 0x00ff0000;
424
                ++iter;
425
                three = true;
426
            }
427
 
428
            uch |= ((*iter << 8) & 0x0000ff00);
429
            ++iter;
430
            uch |= (*iter & 0x000000ff);
431
        }
432
        else
433
            uch = *iter;
434
 
435
        if (three || uch > 0x00ff)
436
        {
437
            int i = 0;
438
            bool found = false;
439
 
440
            while(three && __cht[i].ch != 0xff)
441
            {
442
                if (__cht[i].byte == uch)
443
                {
444
                    out.push_back(__cht[i].ch);
445
                    found = true;
446
                    break;
447
                }
448
 
449
                i++;
450
            }
451
 
452
            three = false;
453
 
454
            if (!found)
455
            {
456
                unsigned ch = ((uch & 0x0300) >> 2) | (uch & 0x003f);
457
                out.push_back(ch);
458
            }
459
        }
460
        else
461
            out.push_back(uch);
462
    }
162 andreas 463
 
70 andreas 464
    return out;
465
#else
11 andreas 466
    char dst[1024];
467
    size_t srclen = 0;
468
    char* pIn, *pInSave;
469
 
470
    srclen = str.length();
471
    memset(&dst[0], 0, sizeof(dst));
472
 
473
    try
474
    {
475
        pIn = new char[srclen + 1];
476
        memcpy(pIn, str.c_str(), srclen);
477
        *(pIn+srclen) = 0;
478
        pInSave = pIn;
479
    }
480
    catch(std::exception& e)
481
    {
482
        MSG_ERROR("Error: " << e.what());
483
        return "";
484
    }
485
 
486
    size_t dstlen = sizeof(dst) - 1;
487
    char* pOut = (char *)dst;
488
 
70 andreas 489
    iconv_t conv = iconv_open("UTF-8", "CP1250");
11 andreas 490
 
491
    if (conv == (iconv_t)-1)
492
    {
70 andreas 493
        MSG_ERROR("Error opening iconv: " << strerror(errno));
11 andreas 494
        delete[] pInSave;
495
        return str;
496
    }
497
 
498
    size_t ret = iconv(conv, &pIn, &srclen, &pOut, &dstlen);
499
    iconv_close(conv);
500
    delete[] pInSave;
501
 
502
    if (ret == (size_t)-1)
503
    {
504
        MSG_ERROR("Error converting a string!");
505
        return str;
506
    }
507
 
508
    return string(dst);
70 andreas 509
#endif
11 andreas 510
}
21 andreas 511
 
93 andreas 512
void *renew(char **mem, size_t old_size, size_t new_size)
21 andreas 513
{
514
    if (old_size == new_size)
93 andreas 515
        return *mem;
21 andreas 516
 
93 andreas 517
    if (!mem || !*mem)
518
        return nullptr;
519
 
21 andreas 520
    try
521
    {
93 andreas 522
        char *memory = new char[new_size];
21 andreas 523
        size_t len = (new_size < old_size) ? new_size : old_size;
93 andreas 524
        memcpy(memory, *mem, len);
525
        delete[] *mem;
526
        *mem = memory;
21 andreas 527
        return memory;
528
    }
529
    catch(std::exception& e)
530
    {
531
        MSG_ERROR(e.what());
93 andreas 532
        throw;
21 andreas 533
    }
534
 
535
    return nullptr;
536
}
537
 
538
string toUpper(string& str)
539
{
540
    string::iterator iter;
541
 
542
    for (iter = str.begin(); iter != str.end(); iter++)
543
        *iter = std::toupper(*iter);
544
 
545
    return str;
546
}
547
 
548
string toLower(string& str)
549
{
550
    string::iterator iter;
551
 
552
    for (iter = str.begin(); iter != str.end(); iter++)
553
        *iter = std::tolower(*iter);
554
 
555
    return str;
556
}
54 andreas 557
 
558
vector<string> splitLine(const string& str)
559
{
560
    DECL_TRACER("splitLine(const string& str)");
561
 
562
    vector<string> lines;
563
    string sl;
96 andreas 564
    string::const_iterator iter;
54 andreas 565
 
96 andreas 566
    if (str.empty())
567
        return lines;
568
 
569
    for (iter = str.begin(); iter != str.end(); iter++)
54 andreas 570
    {
96 andreas 571
        if (*iter == '\r')  // ignore bloating byte coming from brain death windows
54 andreas 572
            continue;
573
 
96 andreas 574
        if (*iter == '\n')
54 andreas 575
        {
576
            lines.push_back(sl);
577
            sl.clear();
578
            continue;
579
        }
580
 
57 andreas 581
        char ch[2];
96 andreas 582
        ch[0] = *iter;
57 andreas 583
        ch[1] = 0;
584
        sl.append(ch);
54 andreas 585
    }
586
 
587
    if (!sl.empty())
588
        lines.push_back(sl);
589
 
590
    return lines;
591
}
592
 
57 andreas 593
vector<string> splitLine(const string& str, int width, int height, SkFont& font, SkPaint& paint)
594
{
595
    DECL_TRACER("splitLine(const string& str, int width, int height, SkFont& font, SkPaint& paint)");
596
 
597
    SkRect rect;
70 andreas 598
    vector<string> lines, words;
57 andreas 599
    SkScalar lnHeight = font.getSize();
600
    int maxLines = (int)((SkScalar)height / lnHeight);
70 andreas 601
    string part, oldPart;
96 andreas 602
 
603
    if (str.empty())
604
        return lines;
605
 
70 andreas 606
    words = StrSplit(str, " \n");
96 andreas 607
    MSG_DEBUG("Found " << words.size() << " words.");
70 andreas 608
    vector<string>::iterator iter;
57 andreas 609
 
96 andreas 610
    if (words.size() == 0)
611
        return lines;
612
 
70 andreas 613
    for (iter = words.begin(); iter != words.end(); ++iter)
57 andreas 614
    {
96 andreas 615
        size_t pos;
616
        bool lineBreak = false;
617
 
618
        if ((pos = iter->find("\n")) != string::npos)
619
        {
620
            if (pos > 0)
164 andreas 621
                *iter = iter->substr(0, pos);
96 andreas 622
            else
623
                *iter = "";
624
 
625
            lineBreak = true;
626
        }
627
 
70 andreas 628
        if (part.empty())
629
            part += *iter;
630
        else
631
            part += " " + *iter;
632
 
57 andreas 633
        font.measureText(part.c_str(), part.length(), SkTextEncoding::kUTF8, &rect, &paint);
634
 
635
        if (rect.width() > (width - 8))
636
        {
70 andreas 637
            if (oldPart.empty())
638
            {
639
                string sample;
640
                size_t len = part.length();
641
                size_t pos = 1, start = 0;
57 andreas 642
 
70 andreas 643
                for (size_t i = 0; i < len; i++)
644
                {
645
                    sample = part.substr(start, pos);
646
                    font.measureText(sample.c_str(), sample.length(), SkTextEncoding::kUTF8, &rect, &paint);
647
 
648
                    if (rect.width() > (width - 8))
649
                    {
163 andreas 650
                        lines.push_back(sample.substr(0, sample.length() - 1)); // Cut off the last character because it is already out of bounds.
70 andreas 651
                        start = i;                                              // Set the new start of the string
652
                        i--;                                                    // We must repeat the last character
653
                        pos = 0;                                                // Reset the position counter
654
                        sample = sample.substr(sample.length() - 1);            // Put the last character into the part.
655
 
656
                        if (lines.size() >= (size_t)maxLines)                   // Break if we've reached the maximum of lines
657
                            return lines;
658
                    }
659
 
660
                    pos++;
661
                }
662
 
663
                oldPart.clear();
664
                part = sample;
665
                continue;
666
            }
667
            else
668
            {
669
                lines.push_back(oldPart);
670
                oldPart.clear();
671
                part = *iter;
672
 
673
                if (lines.size() >= (size_t)maxLines)               // Break if we've reached the maximum of lines
674
                    return lines;
675
 
676
                font.measureText(part.c_str(), part.length(), SkTextEncoding::kUTF8, &rect, &paint);
677
 
678
                if (rect.width() > (width - 8))
679
                    continue;
680
            }
57 andreas 681
        }
96 andreas 682
        else if (lineBreak)
683
        {
684
            lines.push_back(part);
685
            part.clear();
686
        }
57 andreas 687
 
70 andreas 688
        oldPart = part;
57 andreas 689
    }
690
 
70 andreas 691
    if (lines.empty())
692
        lines.push_back(str);
693
    else if (!part.empty())
57 andreas 694
        lines.push_back(part);
695
 
696
    return lines;
697
}
60 andreas 698
 
699
bool isHex(int c)
700
{
701
    if ((c >= '0' && c <= '9') ||
702
        (c >= 'a' && c <= 'f') ||
703
        (c >= 'A' && c <= 'F'))
704
        return true;
705
 
706
    return false;
707
}
708
 
709
int strCaseCompare(const string& str1, const string& str2)
710
{
711
    return strcasecmp(str1.c_str(), str2.c_str());
712
}
63 andreas 713
 
714
std::string fillString(int c, int len)
715
{
716
    if (len < 1 || c < 1 || c > 0x00ffffff)
717
        return string();
718
 
719
    string str;
720
    char ch[4];
721
 
722
    if (c <= 0x00ff)
723
    {
724
        ch[0] = c;
725
        ch[1] = 0;
726
    }
727
    else if (c <= 0x00ffff)
728
    {
729
        ch[0] = c >> 8;
730
        ch[1] = c;
731
        ch[2] = 0;
732
    }
733
    else
734
    {
735
        ch[0] = c >> 16;
736
        ch[1] = c >> 8;
737
        ch[2] = c;
738
        ch[3] = 0;
739
    }
740
 
741
    for (int i = 0; i < len; i++)
742
        str.append(ch);
743
 
744
    return str;
745
}
67 andreas 746
 
747
bool isUTF8(const string& str)
748
{
749
    int c,i,ix,n,j;
750
 
751
    for (i=0, ix = str.length(); i < ix; i++)
752
    {
753
        c = (unsigned char) str[i];
754
 
755
        if (0x00 <= c && c <= 0x7f)
756
            n=0; // 0bbbbbbb
757
        else if ((c & 0xE0) == 0xC0)
758
            n=1; // 110bbbbb
759
        else if ( c==0xed && i<(ix-1) && ((unsigned char)str[i+1] & 0xa0)==0xa0)
760
            return false; //U+d800 to U+dfff
761
        else if ((c & 0xF0) == 0xE0)
762
            n=2; // 1110bbbb
763
        else if ((c & 0xF8) == 0xF0)
764
            n=3; // 11110bbb
765
        else
766
            return false;
767
 
768
        for (j=0; j<n && i<ix; j++) // n bytes matching 10bbbbbb follow ?
769
        {
770
            if ((++i == ix) || (( (unsigned char)str[i] & 0xC0) != 0x80))
771
                return false;
772
        }
773
    }
774
 
775
    return true;
776
}
777
 
778
size_t utf8Strlen(const std::string& str)
779
{
780
    int c,i,ix;
781
    size_t q;
782
 
783
    for (q = 0, i = 0, ix = str.length(); i < ix; i++, q++)
784
    {
157 andreas 785
        c = (unsigned char)str[i];
67 andreas 786
 
157 andreas 787
        if (c >= 0 && c <= 127)
788
            i += 0;
67 andreas 789
        else if ((c & 0xE0) == 0xC0)
157 andreas 790
            i += 1;
67 andreas 791
        else if ((c & 0xF0) == 0xE0)
157 andreas 792
            i += 2;
67 andreas 793
        else if ((c & 0xF8) == 0xF0)
157 andreas 794
            i += 3;
67 andreas 795
        else
796
            return 0;   //invalid utf8
797
    }
798
 
799
    return q;
800
}
801
 
802
uint16_t getUint16(const unsigned char *p, bool big_endian)
803
{
804
    if (!p)
805
        return 0;
806
 
807
    uint16_t num;
808
    memmove(&num, p, sizeof(uint16_t));
809
 
810
    if (!big_endian)
811
    {
812
        uint16_t le_num = ((num >> 8) & 0x00ff) | ((num << 8) & 0xff00);
813
        num = le_num;
814
    }
815
 
816
    return num;
817
}
818
 
819
uint32_t getUint32(const unsigned char *p, bool big_endian)
820
{
821
    if (!p)
822
        return 0;
823
 
824
    uint32_t num;
825
    memmove(&num, p, sizeof(uint32_t));
826
 
827
    if (!big_endian)
828
    {
829
        uint32_t le_num = ((num >> 24) & 0x000000ff) | ((num >> 8) & 0x0000ff00) | ((num << 8) & 0x00ff0000) | ((num << 24) & 0xff000000);
830
        num = le_num;
831
    }
832
 
833
    return num;
834
}
71 andreas 835
 
836
bool endsWith (const std::string &src, const std::string &end)
837
{
838
    vector<string> list;
839
 
840
    if (end.find("|") == string::npos)
841
        list.push_back(end);
842
    else
843
        list = StrSplit(end, "|", false);
844
 
845
    vector<string>::iterator iter;
846
 
847
    for (iter = list.begin(); iter != list.end(); ++iter)
848
    {
849
        size_t len = iter->length();
850
 
851
        if (len > src.length())
852
            continue;
853
 
854
        string part = src.substr(src.length() - len);
855
 
856
        if (part.compare(*iter) == 0)
857
            return true;
858
    }
859
 
860
    return false;
861
}
862
 
863
bool startsWith (const std::string &src, const std::string &start)
864
{
865
    vector<string> list;
866
 
867
    if (start.find("|") == string::npos)
868
        list.push_back(start);
869
    else
870
        list = StrSplit(start, "|", false);
871
 
872
    vector<string>::iterator iter;
873
 
874
    for (iter = list.begin(); iter != list.end(); ++iter)
875
    {
876
        size_t len = iter->length();
877
 
878
        if (len > src.length())
879
            continue;
880
 
881
        string part = src.substr(0, len);
882
 
883
        if (part.compare(*iter) == 0)
884
            return true;
885
    }
886
 
887
    return false;
888
}
889
 
890
std::string dirName (const std::string &path)
891
{
892
    if (path.empty())
893
        return ".";
894
 
895
    size_t len = path.length();
896
 
897
    char *buffer = new char[len+1];
898
    memset(buffer, 0, len+1);
899
    strncpy(buffer, path.c_str(), len);
900
 
901
    char *dir = dirname(buffer);
902
    string ret(dir);
903
    delete[] buffer;
904
    return ret;
905
}
906
 
907
std::string baseName (const std::string &path)
908
{
909
    if (path.empty())
910
        return ".";
911
 
912
    size_t len = path.length();
913
 
914
    char *buffer = new char[len+1];
915
    memset(buffer, 0, len+1);
916
    strncpy(buffer, path.c_str(), len);
917
 
918
    char *dir = basename(buffer);
919
    string ret(dir);
920
    delete[] buffer;
921
    return ret;
922
}
97 andreas 923
 
924
char *strnstr(const char* haystack, const char* needle, size_t len)
925
{
926
    if (!haystack || !needle)
927
        return nullptr;
928
 
929
    size_t needleLen = strlen(needle);
930
 
931
    if (needleLen > len)
932
        return nullptr;
933
 
934
    char *start = (char *)haystack;
935
    size_t pos = 0;
936
 
937
    while ((pos + needleLen) < len)
938
    {
939
        bool match = true;
940
 
941
        for (size_t i = 0; i < needleLen; i++)
942
        {
943
            if (*(start + i) != *(needle + i))
944
            {
945
                match = false;
946
                break;
947
            }
948
        }
949
 
950
        if (match)
951
            return start;
952
 
953
        pos++;
954
        start++;
955
    }
956
 
957
    return nullptr;
958
}
104 andreas 959
 
960
string getCommand(const string& fullCmd)
961
{
962
    DECL_TRACER("getCommand(const string& fullCmd)");
963
 
964
    size_t pos = fullCmd.find_first_of("-");
965
    string cmd;
966
 
967
    if (pos != string::npos)
153 andreas 968
    {
104 andreas 969
        cmd = fullCmd.substr(0, pos);
153 andreas 970
        cmd = toUpper(cmd);
971
    }
104 andreas 972
    else
153 andreas 973
    {
104 andreas 974
        cmd = fullCmd;
153 andreas 975
        cmd = toUpper(cmd);
976
    }
104 andreas 977
 
978
    return cmd;
979
}
162 andreas 980