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