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